home *** CD-ROM | disk | FTP | other *** search
- From peter@sugar.hackercorp.com Tue Dec 11 20:33:09 1990
- From: peter@sugar.hackercorp.com (Peter da Silva)
- Newsgroups: alt.binaries.multimedia
- Subject: Definition of Electronic Arts IFF format
- Date: 10 Dec 90 12:56:36 GMT
- Reply-To: peter@sugar.hackercorp.com (Peter da Silva)
- Organization: Sugar Land Unix - Houston
-
- In a radical move, infomation instead of flames.
-
- Definitions of the Electronic Arts IFF formats for text, sampled sounds,
- musical scores, and images.
-
- : This archive contains the following files...
- : '8svx'
- : 'ea.iff.85'
- : 'ftxt'
- : 'ilbm'
- : 'smus'
- : To extract them, run the following through /bin/sh
- echo x - 8svx
- sed 's/^X//' > 8svx << '//END'
- X"8SVX" IFF 8-Bit Sampled Voice
- X
- XDate: February 7, 1985
- XFrom: Steve Hayes and Jerry Morrison, Electronic Arts
- XStatus: Adopted
- X
- X1. Introduction
- X
- XThis memo is the IFF supplement for FORM "8SVX". An 8SVX is an IFF
- X"data section" or "FORM" (which can be an IFF file or a part of one)
- Xcontaining a digitally sampled audio voice consisting of 8-bit samples.
- XA voice can be a one-shot sound orQwith repetition and pitch scalingQa
- Xmusical instrument. "EA IFF 85" is Electronic Arts' standard interchange
- Xfile format. [See "EA IFF 85" Standard for Interchange Format Files.]
- X
- XThe 8SVX format is designed for playback hardware that uses 8-bit
- Xsamples attenuated by a volume control for good overall signal-to-noise
- Xratio. So a FORM 8SVX stores 8-bit samples and a volume level.
- X
- XA similar data format (or two) will be needed for higher resolution
- Xsamples (typically 12 or 16 bits). Properly converting a high resolution
- Xsample down to 8 bits requires one pass over the data to find the
- Xminimum and maximum values and a second pass to scale each sample
- Xinto the range -128 through 127. So it's reasonable to store higher
- Xresolution data in a different FORM type and convert between them.
- X
- XFor instruments, FORM 8SVX can record a repeating waveform optionally
- Xpreceded by a startup transient waveform. These two recorded signals
- Xcan be pre-synthesized or sampled from an acoustic instrument. For
- Xmany instruments, this representation is compact. FORM 8SVX is less
- Xpractical for an instrument whose waveform changes from cycle to cycle
- Xlike a plucked string, where a long sample is needed for accurate
- Xresults.
- X
- XFORM 8SVX can store an "envelope" or "amplitude contour" to enrichen
- Xmusical notes. A future voice FORM could also store amplitude, frequency,
- Xand filter modulations.
- X
- XFORM 8SVX is geared for relatively simple musical voices, where one
- Xwaveform per octave is sufficient, where the waveforms for the different
- Xoctaves follows a factor-of-two size rule, and where one envelope
- Xis adequate for all octaves. You could store a more general voice
- Xas a LIST containing one or more FORMs 8SVX per octave. A future voice
- XFORM could go beyond one "one-shot" waveform and one "repeat" waveform
- Xper octave.
- X
- XSection 2 defines the required property sound header "VHDR", optional
- Xproperties name "NAME", copyright "(c)J", and author "AUTH", the optional
- Xannotation data chunk "ANNO", the required data chunk "BODY", and
- Xoptional envelope chunks "ATAK" and "RLSE". These are the "standard"
- Xchunks. Specialized chunks for private or future needs can be added
- Xlater, e.g. to hold a frequency contour or Fourier series coefficients.
- XThe 8SVX syntax is summarized in Appendix A as a regular expression
- Xand in Appendix B as an example box diagram. Appendix C explains the
- Xoptional Fibonacci-delta compression algorithm.
- X
- XCaution: The VHDR structure Voice8Header changed since draft proposal
- X#4! The new structure is incompatible with the draft version.
- X
- X
- X
- XReference:
- X
- X"EA IFF 85" Standard for Interchange Format Files describes the underlying
- Xconventions for all IFF files.
- X
- XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
- X
- XElectronic Arts[tm] is a trademark of Electronic Arts.
- X
- XMacWrite[tm] is a trademark of Apple Computer, Inc.
- X
- X
- X
- X2. Standard Data and Property Chunks
- X
- XFORM 8SVX stores all the waveform data in one body chunk "BODY". It
- Xstores playback parameters in the required header chunk "VHDR". "VHDR"
- Xand any optional property chunks "NAME", "(c)J", and "AUTH" must all
- Xappear before the BODY chunk. Any of these properties may be shared
- Xover a LIST of FORMs 8SVX by putting them in a PROP 8SVX. [See "EA
- XIFF 85" Standard for Interchange Format Files.]
- X
- XBackground
- X
- XThere are two ways to use FORM 8SVX: as a one-shot sampled sound or
- Xas a sampled musical instrument that plays "notes". Storing both kinds
- Xof sounds in the same kind of FORM makes it easy to play a one-shot
- Xsound as a (staccato) instrument or an instrument as a (one-note)
- Xsound.
- X
- XA one-shot sound is a series of audio data samples with a nominal
- Xplayback rate and amplitude. The recipient program can optionally
- Xadjust or modulate the amplitude and playback data rate.
- X
- XFor musical instruments, the idea is to store a sampled (or pre-synthesized)
- Xwaveform that will be parameterized by pitch, duration, and amplitude
- Xto play each "note". The creator of the FORM 8SVX can supply a waveform
- Xper octave over a range of octaves for this purpose. The intent is
- Xto perform a pitch by selecting the closest octave's waveform and
- Xscaling the playback data rate. An optional "one-shot" waveform supplies
- Xan arbitrary startup transient, then a "repeat" waveform is iterated
- Xas long as necessary to sustain the note.
- X
- XA FORM 8SVX can also store an envelope to modulate the waveform. Envelopes
- Xare mostly useful for variable-duration notes but could be used for
- Xone-shot sounds, too.
- X
- XThe FORM 8SVX standard has some restrictions. For example, each octave
- Xof data must be twice as long as the next higher octave. Most sound
- Xdriver software and hardware imposes additional restrictions. E.g.
- Xthe Amiga sound hardware requires an even number of samples in each
- Xone-shot and repeat waveform.
- X
- XRequired Property VHDR
- X
- XThe required property "VHDR" holds a Voice8Header structure as defined
- Xin these C declarations and following documentation. This structure
- Xholds the playback parameters for the sampled waveforms in the BODY
- Xchunk. (See "Data Chunk BODY", below, for the storage layout of these
- Xwaveforms.)
- X
- X#define ID_8SVX MakeID('8', 'S', 'V', 'X')
- X#define ID_VHDR MakeID('V', 'H', 'D', 'R')
- X
- Xtypedef LONG Fixed;
- X /* A fixed-point value, 16 bits to the left of the point and 16
- X * to the right. A Fixed is a number of 216ths, i.e. 65536ths. */
- X
- X#define Unity 0x10000L /* Unity = Fixed 1.0 = maximum volume */
- X
- X/* sCompression: Choice of compression algorithm applied to the samples. */
- X
- X#define sCmpNone 0 /* not compressed */
- X#define sCmpFibDelta 1 /* Fibonacci-delta encoding (Appendix C) */
- X
- X/* Can be more kinds in the future. */
- X
- Xtypedef struct {
- X ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */
- X repeatHiSamples, /* # samples in the high octave repeat part */
- X samplesPerHiCycle; /* # samples/cycle in high octave, else 0 */
- X UWORD samplesPerSec; /* data sampling rate */
- X UBYTE ctOctave, /* # octaves of waveforms */
- X sCompression; /* data compression technique used */
- X Fixed volume; /* playback volume from 0 to Unity (full
- X * volume). Map this value into the output
- X * hardware's dynamic range. */
- X } Voice8Header;
- X
- X[Implementation details. Fields are filed in the order shown. The
- XUBYTE fields are byte-packed (2 per 16-bit word). MakeID is a C macro
- Xdefined in the main IFF document and in the source file IFF.h.]
- X
- XA FORM 8SVX holds waveform data for one or more octaves, each containing
- Xa one-shot part and a repeat part. The fields oneShotHiSamples and
- XrepeatHiSamples tell the number of audio samples in the two parts
- Xof the highest frequency octave. Each successive (lower frequency)
- Xoctave contains twice as many data samples in both its one-shot and
- Xrepeat parts. One of these two parts can be empty across all octaves.
- X
- XNote: Most audio output hardware and software has limitations. The
- XAmiga computer's sound hardware requires that all one-shot and repeat
- Xparts have even numbers of samples. Amiga sound driver software would
- Xhave to adjust an odd-sized waveform, ignore an odd-sized lowest octave,
- Xor ignore odd FORMs 8SVX altogether. Some other output devices require
- Xall sample sizes to be powers of two.
- X
- XThe field samplesPerHiCycle tells the number of samples/cycle in the
- Xhighest frequency octave of data, or else 0 for "unknown". Each successive
- X(lower frequency) octave contains twice as many samples/cycle. The
- XsamplesPerHiCycle value is needed to compute the data rate for a desired
- Xplayback pitch.
- X
- XActually, samplesPerHiCycle is an average number of samples/cycle.
- XIf the one-shot part contains pitch bends, store the samples/cycle
- Xof the repeat part in samplesPerHiCycle. The division repeatHiSamples/samplesPe
- XrHiCycle should yield an integer number of cycles. (When the repeat
- Xwaveform is repeated, a partial cycle would come out as a higher-frequency
- Xcycle with a "click".)
- X
- XMore limitations: Some Amiga music drivers require samplesPerHiCycle
- Xto be a power of two in order to play the FORM 8SVX as a musical instrument
- Xin tune. They may even assume samplesPerHiCycle is a particular power
- Xof two without checking. (If samplesPerHiCycle is different by a factor
- Xof two, the instrument will just be played an octave too low or high.)
- X
- XThe field samplesPerSec gives the sound sampling rate. A program may
- Xadjust this to achieve frequency shifts or vary it dynamically to
- Xachieve pitch bends and vibrato. A program that plays a FORM 8SVX
- Xas a musical instrument would ignore samplesPerSec and select a playback
- Xrate for each musical pitch.
- X
- XThe field ctOctave tells how many octaves of data are stored in the
- XBODY chunk. See "Data Chunk BODY", below, for the layout of the octaves.
- X
- XThe field sCompression indicates the compression scheme, if any, that
- Xwas applied to the entire set of data samples stored in the BODY chunk.
- XThis field should contain one of the values defined above. Of course,
- Xthe matching decompression algorithm must be applied to the BODY data
- Xbefore the sound can be played. (The Fibonacci-delta encoding scheme
- XsCmpFibDelta is described in Appendix C.) Note that the whole series
- Xof data samples is compressed as a unit.
- X
- XThe field volume gives an overall playback volume for the waveforms
- X(all octaves). It lets the 8-bit data samples use the full range -128
- Xthrough 127 for good signal-to-noise ratio and be attenuated on playback
- Xto the desired level. The playback program should multiply this value
- Xby a "volume control" and perhaps by a playback envelope (see ATAK
- Xand RLSE, below).
- X
- XRecording a one-shot sound. To store a one-shot sound in a FORM 8SVX,
- Xset oneShotHiSamples = number of samples, repeatHiSamples = 0 ,
- XsamplesPerHiCycle = 0, samplesPerSec = sampling rate, and ctOctave = 1.
- XScale the signal amplitude to the full sampling range -128 through 127. Set
- Xvolume so the sound will playback at the desired volume level. If
- Xyou set the samplesPerHiCycle field properly, the data can also be
- Xused as a musical instrument.
- X
- XExperiment with data compression. If the decompressed signal sounds
- Xok, store the compressed data in the BODY chunk and set sCompression
- Xto the compression code number.
- X
- XRecording a musical instrument. To store a musical instrument in a
- XFORM 8SVX, first record or synthesize as many octaves of data as you
- Xwant to make available for playback. Set ctOctaves to the count of
- Xoctaves. From the recorded data, excerpt an integral number of steady
- Xstate cycles for the repeat part and set repeatHiSamples and samplesPerHiCycle.
- XEither excerpt a startup transient waveform and set oneShotHiSamples,
- Xor else set oneShotHiSamples to 0. Remember, the one-shot and repeat
- Xparts of each octave must be twice as long as those of the next higher
- Xoctave. Scale the signal amplitude to the full sampling range and
- Xset volume to adjust the instrument playback volume. If you set the
- XsamplesPerSec field properly, the data can also be used as a one-shot
- Xsound.
- X
- XA distortion-introducing compressor like sCmpFibDelta is not recommended
- Xfor musical instruments, but you might try it anway.
- X
- XTypically, creators of FORM 8SVX record an acoustic instrument at
- Xjust one frequency. Decimate (down- sample with filtering) to compute
- Xhigher octaves. Interpolate to compute lower octaves.
- X
- XIf you sample an acoustic instrument at different octaves, you may
- Xfind it hard to make the one-shot and repeat waveforms follow the
- Xfactor-of-two rule for octaves. To compensate, lengthen an octave's
- Xone-shot part by appending replications of the repeating cycle or
- Xprepending zeros. (This will have minimal impact on the sound's start
- Xtime.) You may be able to equalize the ratio one-shot-samples : repeat-samples
- Xacross all octaves.
- X
- XNote that a "one-shot sound" may be played as a "musical instrument"
- Xand vice versa. However, an instrument player depends on samplesPerHiCycle,
- Xand a one-shot player depends on samplesPerSec.
- X
- XPlaying a one-shot sound. To play any FORM 8SVX data as a one-shot
- Xsound, first select an octave if ctOctave > 1. (The lowest-frequency
- Xoctave has the greatest resolution.) Play the one-shot samples then
- Xthe repeat samples, scaled by volume, at a data rate of samplesPerSec.
- XOf course, you may adjust the playback rate and volume. You can play
- Xout an envelope, too. (See ATAK and RLSE, below.)
- X
- XPlaying a musical note. To play a musical note using any FORM 8SVX,
- Xfirst select the nearest octave of data from those available. Play
- Xthe one-shot waveform then cycle on the repeat waveform as long as
- Xneeded to sustain the note. Scale the signal by volume, perhaps also
- Xby an envelope, and by a desired note volume. Select a playback data
- Xrate s samples/second to achieve the desired frequency (in Hz):
- Xfrequency = sJ/JsamplesPerHiCycle
- Xfor the highest frequency octave.
- X
- XThe idea is to select an octave and one of 12 sampling rates (assuming
- Xa 12-tone scale). If the FORM 8SVX doesn't have the right octave,
- Xyou can decimate or interpolate from the available data.
- X
- XWhen it comes to musical instruments, FORM 8SVX is geared for a simple
- Xsound driver. Such a driver uses a single table of 12 data rates to
- Xreach all notes in all octaves. That's why 8SVX requires each octave
- Xof data to have twice as many samples as the next higher octave. If
- Xyou restrict samplesPerHiCycle to a power of two, you can use a predetermined
- Xtable of data rates.
- X
- XOptional Text Chunks NAME, (c), AUTH, ANNO
- X
- XSeveral text chunks may be included in a FORM 8SVX to keep ancillary
- Xinformation.
- X
- XThe optional property "NAME" names the voice, for instance "tubular
- Xbells".
- X
- XThe optional property "(c)J" holds a copyright notice for the voice.
- XThe chunk ID "(c)J" serves as the copyright characters ")J". E.g.
- Xa "(c)J" chunk containing "1986 Electronic Arts" means ") 1986 Electronic
- XArts".
- X
- XThe optional property "AUTH" holds the name of the instrument's "author"
- Xor "creator".
- X
- XThe chunk types "NAME", "(c) ", and "AUTH" are property chunks. Putting
- Xmore than one NAME (or other) property in a FORM is redundant. Just
- Xthe last NAME counts. A property should be shorter than 256 characters.
- XProperties can appear in a PROP 8SVX to share them over a LIST of
- XFORMs 8SVX.
- X
- XThe optional data chunk "ANNO" holds any text annotations typed in
- Xby the author.
- X
- XAn ANNO chunk is not a property chunk, so you can put more than one
- Xin a FORM 8SVX. You can make ANNO chunks any length up to 231 - 1
- Xcharacters, but 32767 is a practical limit. Since they're not properties,
- XANNO chunks don't belong in a PROP 8SVX. That means they can't be
- Xshared over a LIST of FORMs 8SVX.
- X
- XSyntactically, each of these chunks contains an array of 8-bit ASCII
- Xcharacters in the range " " (SP, hex 20) through "~" (tilde, hex 7F),
- Xjust like a standard "TEXT" chunk. [See "Strings, String Chunks, and
- XString Properties" in "EA IFF 85" Electronic Arts Interchange File
- XFormat.] The chunk's ckSize field holds the count of characters.
- X
- X#define ID_NAME MakeID('N', 'A', 'M', 'E')
- X/* NAME chunk contains a CHAR[], the voice's name. */
- X
- X#define ID_Copyright MakeID('(', 'c', ')', ' ')
- X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
- X
- X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
- X/* AUTH chunk contains a CHAR[], the author's name. */
- X
- X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
- X/* ANNO chunk contains a CHAR[], author's text annotations. */
- X
- XRemember to store a 0 pad byte after any odd-length chunk.
- X
- XOptional Data Chunks ATAK and RLSE
- X
- XThe optional data chunks ATAK and RLSE together give a piecewise-linear
- X"envelope" or "amplitude contour". This contour may be used to modulate
- Xthe sound during playback. It's especially useful for playing musical
- Xnotes of variable durations. Playback programs may ignore the supplied
- Xenvelope or substitute another.
- X
- X#define ID_ATAK MakeID('A', 'T', 'A', 'K')
- X#define ID_RLSE MakeID('R', 'L', 'S', 'E')
- X
- Xtypedef struct {
- X UWORD duration; /* segment duration in milliseconds, > 0 */
- X Fixed dest; /* destination volume factor */
- X } EGPoint;
- X
- X/* ATAK and RLSE chunks contain an EGPoint[], piecewise-linear envelope.*/
- X/* The envelope defines a function of time returning Fixed values. It's
- X * used to scale the nominal volume specified in the Voice8Header. */
- X
- XTo explain the meaning of the ATAK and RLSE chunks, we'll overview
- Xthe envelope generation algorithm. Start at 0 volume, step through
- Xthe ATAK contour, then hold at the sustain level (the last ATAK EGPoint's
- Xdest), and then step through the RLSE contour. Begin the release at
- Xthe desired note stop time minus the total duration of the release
- Xcontour (the sum of the RLSE EGPoints' durations). The attack contour
- Xshould be cut short if the note is shorter than the release contour.
- X
- XThe envelope is a piecewise-linear function. The envelope generator
- Xinterpolates between the EGPoints.
- X
- XRemember to multiply the envelope function by the nominal voice header
- Xvolume and by any desired note volume.
- X
- XFigure 1 shows an example envelope. The attack period is described
- Xby 4 EGPoints in an ATAK chunk. The release period is described by
- X4 EGPoints in a RLSE chunk. The sustain period in the middle just
- Xholds the final ATAK level until it's time for the release.
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X Figure 1. Amplitude contour.
- X
- XNote: The number of EGPoints in an ATAK or RLSE chunk is its ckSize
- X/ sizeof(EGPoint). In RAM, the playback program may terminate the
- Xarray with a 0 duration EGPoint.
- X
- XIssue: Synthesizers also provide frequency contour (pitch bend), filtering
- Xcontour (wah-wah), amplitude oscillation (tremolo), frequency oscillation
- X(vibrato), and filtering oscillation (leslie). In the future, we may
- Xdefine optional chunks to encode these modulations. The contours can
- Xbe encoded in linear segments. The oscillations can be stored as segments
- Xwith rate and depth parameters.
- X
- XData Chunk BODY
- X
- XThe BODY chunk contains the audio data samples.
- X
- X#define ID_BODY MakeID('B', 'O', 'D', 'Y')
- X
- Xtypedef character BYTE; /* 8 bit signed number, -128 through 127. */
- X
- X/* BODY chunk contains a BYTE[], array of audio data samples. */
- X
- XThe BODY contains data samples grouped by octave. Within each octave
- Xare one-shot and repeat portions. Figure 2 depicts this arrangement
- Xof samples for an 8SVX where oneShotHiSamples = 24, repeatHiSamples
- X= 16, samplesPerHiCycle = 8, and ctOctave = 3. The major divisions
- Xare octaves, the intermediate divisions separate the one-shot and
- Xrepeat portions, and the minor divisions are cycles.
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X Figure 2. BODY subdivisions.
- X
- XIn general, the BODY has ctOctave octaves of data. The highest frequency
- Xoctave comes first, comprising the fewest samples: oneShotHiSamples
- X+ repeatHiSamples. Each successive octave contains twice as many samples
- Xas the next higher octave but the same number of cycles. The lowest
- Xfrequency octave comes last with the most samples: 2ctOctave-1 * (oneShotHiSamp
- Xles + repeatHiSamples).
- X
- XThe number of samples in the BODY chunk is
- X
- X 0 (ctOctave-1)
- X(2 + ... + 2 * (oneShotHiSamples + repeatHiSamples)
- X
- XFigure 3, below, looks closer at an example waveform within one octave
- Xof a different BODY chunk. In this example, oneShotHiSamples / samplesPerHiCycl
- Xe = 2 cycles and repeatHiSamples / samplesPerHiCycle = 1 cycle.
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X Figure 3. Example waveform.
- X
- XTo avoid playback "clicks", the one-shot part should begin with a
- Xsmall sample value, and the one-shot part should flow smoothly into
- Xthe repeat part, and the end of the repeat part should flow smoothly
- Xinto the beginning of the repeat part.
- X
- XIf the VHDR field sCompression - sCmpNone, the BODY chunk is just
- Xan array of data bytes to feed through the specified decompresser
- Xfunction. All this stuff about sample sizes, octaves, and repeat parts
- Xapplies to the decompressed data.
- X
- XBe sure to follow an odd-length BODY chunk with a 0 pad byte.
- X
- XOther Chunks
- X
- XIssue: In the future, we may define an optional chunk containing Fourier
- Xseries coefficients for a repeating waveform. An editor for this kind
- Xof synthesized voice could modify the coefficients and regenerate
- Xthe waveform.
- X
- X
- X
- XAppendix A. Quick Reference
- X
- XType Definitions
- X
- X#define ID_8SVX MakeID('8', 'S', 'V', 'X')
- X#define ID_VHDR MakeID('V', 'H', 'D', 'R')
- X
- Xtypedef LONG Fixed; /* A fixed-point value, 16 bits to the left
- X * of the point and 16 to the right. A Fixed
- X * is a number of 216ths, i.e. 65536ths. */
- X
- X#define Unity 0x10000L /* Unity = Fixed 1.0 = maximum volume */
- X
- X/* sCompression: Choice of compression algorithm applied to the samples */
- X
- X#define sCmpNone 0 /* not compressed */
- X#define sCmpFibDelta 1 /* Fibonacci-delta encoding (Appendix C) */
- X /* Can be more kinds in the future. */
- X
- Xtypedef struct {
- X ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */
- X repeatHiSamples, /* # samples in the high octave repeat part */
- X samplesPerHiCycle; /* # samples/cycle in high octave, else 0 */
- X UWORD samplesPerSec; /* data sampling rate */
- X UBYTE ctOctave, /* # octaves of waveforms */
- X sCompression; /* data compression technique used */
- X Fixed volume; /* playback volume from 0 to Unity (full
- X * volume). Map this value into the output
- X * hardware's dynamic range. */
- X } Voice8Header;
- X
- X#define ID_NAME MakeID('N', 'A', 'M', 'E')
- X/* NAME chunk contains a CHAR[], the voice's name. */
- X
- X#define ID_Copyright MakeID('(', 'c', ')', ' ')
- X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
- X
- X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
- X/* AUTH chunk contains a CHAR[], the author's name. */
- X
- X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
- X/* ANNO chunk contains a CHAR[], author's text annotations. */
- X
- X#define ID_ATAK MakeID('A', 'T', 'A', 'K')
- X#define ID_RLSE MakeID('R', 'L', 'S', 'E')
- X
- Xtypedef struct {
- X UWORD duration; /* segment duration in milliseconds, > 0 */
- X Fixed dest; /* destination volume factor */
- X } EGPoint;
- X
- X/* ATAK and RLSE chunks contain an EGPoint[], piecewise-linear envelope. */
- X/* The envelope defines a function of time returning Fixed values. It's
- X * used to scale the nominal volume specified in the Voice8Header. */
- X
- X#define ID_BODY MakeID('B', 'O', 'D', 'Y')
- X
- Xtypedef character BYTE; /* 8 bit signed number, -128 through 127. */
- X
- X/* BODY chunk contains a BYTE[], array of audio data samples. */
- X
- X8SVX Regular Expression
- X
- XHere's a regular expression summary of the FORM 8SVX syntax. This
- Xcould be an IFF file or part of one.
- X
- X8SVX ::= "FORM" #{ "8SVX" VHDR [NAME] [Copyright] [AUTH] ANNO*
- X [ATAK] [RLSE] BODY }
- X
- XVHDR ::= "VHDR" #{ Voice8Header }
- XNAME ::= "NAME" #{ CHAR* } [0]
- XCopyright ::= "(c) " #{ CHAR* } [0]
- XAUTH ::= "AUTH" #{ CHAR* } [0]
- XANNO ::= "ANNO" #{ CHAR* } [0]
- X
- XATAK ::= "ATAK" #{ EGPoint* }
- XRLSE ::= "RLSE" #{ EGPoint* }
- XBODY ::= "FORM" #{ BYTE* } [0]
- X
- XThe token "#" represents a ckSize LONG count of the following {braced}
- Xdata bytes. E.g. a VHDR's "#" should equal sizeof(Voice8Header). Literal
- Xitems are shown in "quotes", [square bracket items] are optional,
- Xand "*" means 0 or more replications. A sometimes-needed pad byte
- Xis shown as "[0]".
- X
- XActually, the order of chunks in a FORM 8SVX is not as strict as this
- Xregular expression indicates. The property chunks VHDR, NAME, Copyright,
- Xand AUTH may actually appear in any order as long as they all precede
- Xthe BODY chunk. The optional data chunks ANNO, ATAK, and RLSE don't
- Xhave to precede the BODY chunk. And of course, new kinds of chunks
- Xmay appear inside a FORM 8SVX in the future.
- X
- X
- XAppendix B. 8SVX Example
- X
- XHere's a box diagram for a simple example containing the three octave
- XBODY shown earlier in Figure 2.
- X
- X +-----------------------------------+
- X |'FORM' 362 |
- X +-----------------------------------+
- X |'8SVX' |
- X +-----------------------------------+
- X | +-----------------------------+ |
- X | |'VHDR' 20 | |
- X | |24,16,8,10000,3,0,1.0 | |
- X | +-----------------------------+ |
- X | +-----------------------------+ |
- X | |'NAME' 11 | |
- X | |'bass guitar' | |
- X | +-----------------------------+ |
- X | 0 |
- X | +-----------------------------+ |
- X | |'(c)' 20 | |
- X | |1985 Electronic Arts | |
- X | +-----------------------------+ |
- X | +-----------------------------+ |
- X | |'BODY' 280 | |
- X | |1, 2, 3, 4, ... | |
- X | +-----------------------------+ |
- X +-----------------------------------+
- X
- XThe "0" after the NAME chunk is a pad byte.
- X
- X
- X
- XAppendix B. Standards Committee
- X
- XThe following people contributed to the design of this IFF standard:
- X
- XBob "Kodiak" Burns, Commodore-Amiga
- XR. J. Mical, Commodore-Amiga
- XJerry Morrison, Electronic Arts
- XGreg Riker, Electronic Arts
- XSteve Shaw, Electronic Arts
- XBarry Walsh, Commodore-Amiga
- X
- X
- XThe "0" after the NAME chunk is a pad byte.
- X
- X
- X
- XAppendix C. Fibonacci Delta Compression
- X
- XThis is Steve Hayes' Fibonacci Delta sound compression technique.
- XIt's like the traditional delta encoding but encodes each delta in
- Xa mere 4 bits. The compressed data is half the size of the original
- Xdata plus a 2-byte overhead for the initial value. This much compression
- Xintroduces some distortion, so try it out and use it with discretion.
- X
- XTo achieve a reasonable slew rate, this algorithm looks up each stored
- X4-bit value in a table of Fibonacci numbers. So very small deltas
- Xare encoded precisely while larger deltas are approximated. When it
- Xhas to make approximations, the compressor should adjust all the values
- X(forwards and backwards in time) for minimum overall distortion.
- X
- XHere is the decompressor written in the C programming language.
- X
- X/* Fibonacci delta encoding for sound data. */
- X
- XBYTE codeToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
- X
- X/* Unpack Fibonacci-delta encoded data from n byte source buffer into 2*n byte
- X * dest buffer, given initial data value x. It returns the last data value x
- X * so you can call it several times to incrementally decompress the data. */
- X
- Xshort D1Unpack(source, n, dest, x)
- X BYTE source[], dest[];
- X LONG n;
- X BYTE x;
- X {
- X BYTE d;
- X LONG i, lim;
- X
- X lim = n <<<< 1;
- X for (i = 0; i << lim; ++i)
- X {
- X /* Decode a data nybble; high nybble then low nybble. */
- X d = source[i >> 1]; /* get a pair of nybbles */
- X if (i & 1) /* select low or high nybble? */
- X d &= 0xf; /* mask to get the low nybble */
- X else
- X d >>= 4; /* shift to get the high nybble */
- X x += codeToDelta[d]; /* add in the decoded delta */
- X dest[i] = x; /* store a 1-byte sample */
- X }
- X return(x);
- X }
- X
- X/* Unpack Fibonacci-delta encoded data from n byte source buffer into 2*(n-2)
- X * byte dest buffer. Source buffer has a pad byte, an 8-bit initial value,
- X * followed by n-2 bytes comprising 2*(n-2) 4-bit encoded samples. */
- X
- Xvoid DUnpack(source, n, dest)
- X BYTE source[], dest[];
- X LONG n;
- X {
- X D1Unpack(source + 2, n - 2, dest, source[1]);
- X }
- //END
- echo x - ea.iff.85
- sed 's/^X//' > ea.iff.85 << '//END'
- X"EA IFF 85" Standard for Interchange Format Files
- X
- XDocument Date: January 14, 1985
- XFrom: Jerry Morrison, Electronic Arts
- XStatus of Standard: Released and in use
- X
- X1. Introduction
- X
- XStandards are Good for Software Developers
- X
- XAs home computer hardware evolves to better and better media machines,
- Xthe demand increases for higher quality, more detailed data. Data
- Xdevelopment gets more expensive, requires more expertise and better
- Xtools, and has to be shared across projects. Think about several ports
- Xof a product on one CD-ROM with 500M Bytes of common data!
- X
- XDevelopment tools need standard interchange file formats. Imagine
- Xscanning in images of "player" shapes, moving them to a paint program
- Xfor editing, then incorporating them into a game. Or writing a theme
- Xsong with a Macintosh score editor and incorporating it into an Amiga
- Xgame. The data must at times be transformed, clipped, filled out,
- Xand moved across machine kinds. Media projects will depend on data
- Xtransfer from graphic, music, sound effect, animation, and script
- Xtools.
- X
- XStandards are Good for Software Users
- X
- XCustomers should be able to move their own data between independently
- Xdeveloped software products. And they should be able to buy data libraries
- Xusable across many such products. The types of data objects to exchange
- Xare open-ended and include plain and formatted text, raster and structured
- Xgraphics, fonts, music, sound effects, musical instrument descriptions,
- Xand animation.
- X
- XThe problem with expedient file formats typically memory dumps is
- Xthat they're too provincial. By designing data for one particular
- Xuse (e.g. a screen snapshot), they preclude future expansion (would
- Xyou like a full page picture? a multi-page document?). In neglecting
- Xthe possibility that other programs might read their data, they fail
- Xto save contextual information (how many bit planes? what resolution?).
- XIgnoring that other programs might create such files, they're intolerant
- Xof extra data (texture palette for a picture editor), missing data
- X(no color map), or minor variations (smaller image). In practice,
- Xa filed representation should rarely mirror an in-memory representation.
- XThe former should be designed for longevity; the latter to optimize
- Xthe manipulations of a particular program. The same filed data will
- Xbe read into different memory formats by different programs.
- X
- XThe IFF philosophy: "A little behind-the-scenes conversion when programs
- Xread and write files is far better than NxM explicit conversion utilities
- Xfor highly specialized formats."
- X
- XSo we need some standardization for data interchange among development
- Xtools and products. The more developers that adopt a standard, the
- Xbetter for all of us and our customers.
- X
- XHere is "EA IFF 1985"
- X
- XHere is our offering: Electronic Arts' IFF standard for Interchange
- XFile Format. The full name is "EA IFF 1985". Alternatives and justifications
- Xare included for certain choices. Public domain subroutine packages
- Xand utility programs are available to make it easy to write and use
- XIFF-compatible programs.
- X
- XPart 1 introduces the standard. Part 2 presents its requirements and
- Xbackground. Parts 3, 4, and 5 define the primitive data types, FORMs,
- Xand LISTs, respectively, and how to define new high level types. Part
- X6 specifies the top level file structure. Appendix A is included for
- Xquick reference and Appendix B names the committee responsible for
- Xthis standard.
- X
- XReferences
- X
- XAmerican National Standard Additional Control Codes for Use with ASCII,
- XANSI standard 3.64-1979 for an 8-bit character set. See also ISO standard
- X2022 and ISO/DIS standard 6429.2.
- X
- XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
- X
- XC, A Reference Manual, Samuel P. Harbison and Guy L. Steele Jr., Tartan
- XLaboratories. Prentice-Hall, Englewood Cliffs, NJ, 1984.
- X
- XCompiler Construction, An Advanced Course, edited by F. L. Bauer and
- XJ. Eickel (Springer-Verlag, 1976). This book is one of many sources
- Xfor information on recursive descent parsing.
- X
- XDIF Technical Specification (c)1981 by Software Arts, Inc. DIF[tm] is
- Xthe format for spreadsheet data interchange developed by Software
- XArts, Inc.
- XDIF[tm] is a trademark of Software Arts, Inc.
- X
- XElectronic Arts[tm] is a trademark of Electronic Arts.
- X
- X"FTXT" IFF Formatted Text, from Electronic Arts. IFF supplement document
- Xfor a text format.
- X
- XInside Macintosh (c) 1982, 1983, 1984, 1985 Apple Computer, Inc., a
- Xprogrammer's reference manual.
- XApple(R) is a trademark of Apple Computer, Inc.
- XMacintosh[tm] is a trademark licensed to Apple Computer, Inc.
- X
- X"ILBM" IFF Interleaved Bitmap, from Electronic Arts. IFF supplement
- Xdocument for a raster image format.
- X
- XM68000 16/32-Bit Microprocessor Programmer's Reference Manual(c) 1984,
- X1982, 1980, 1979 by Motorola, Inc.
- X
- XPostScript Language Manual (c) 1984 Adobe Systems Incorporated.
- XPostScript[tm] is a trademark of Adobe Systems, Inc.
- XTimes and Helvetica(R) are trademarks of Allied Corporation.
- X
- XInterScript: A Proposal for a Standard for the Interchange of Editable
- XDocuments (c)1984 Xerox Corporation.
- XIntroduction to InterScript (c) 1985 Xerox Corporation.
- X
- X
- X
- X2. Background for Designers
- X
- XPart 2 is about the background, requirements, and goals for the standard.
- XIt's geared for people who want to design new types of IFF objects.
- XPeople just interested in using the standard may wish to skip this
- Xpart.
- X
- XWhat Do We Need?
- X
- XA standard should be long on prescription and short on overhead. It
- Xshould give lots of rules for designing programs and data files for
- Xsynergy. But neither the programs nor the files should cost too much
- Xmore than the expedient variety. While we're looking to a future with
- XCD-ROMs and perpendicular recording, the standard must work well on
- Xfloppy disks.
- X
- XFor program portability, simplicity, and efficiency, formats should
- Xbe designed with more than one implementation style in mind. (In practice,
- Xpure stream I/O is adequate although random access makes it easier
- Xto write files.) It ought to be possible to read one of many objects
- Xin a file without scanning all the preceding data. Some programs need
- Xto read and play out their data in real time, so we need good compromises
- Xbetween generality and efficiency.
- X
- XAs much as we need standards, they can't hold up product schedules.
- XSo we also need a kind of decentralized extensibility where any software
- Xdeveloper can define and refine new object types without some "standards
- Xauthority" in the loop. Developers must be able to extend existing
- Xformats in a forward- and backward-compatible way. A central repository
- Xfor design information and example programs can help us take full
- Xadvantage of the standard.
- X
- XFor convenience, data formats should heed the restrictions of various
- Xprocessors and environments. E.g. word-alignment greatly helps 68000
- Xaccess at insignificant cost to 8088 programs.
- X
- XOther goals include the ability to share common elements over a list
- Xof objects and the ability to construct composite objects containing
- Xother data objects with structural information like directories.
- X
- XAnd finally, "Simple things should be simple and complex things should
- Xbe possible." Alan Kay.
- X
- XThink Ahead
- X
- XLet's think ahead and build programs that read and write files for
- Xeach other and for programs yet to be designed. Build data formats
- Xto last for future computers so long as the overhead is acceptable.
- XThis extends the usefulness and life of today's programs and data.
- X
- XTo maximize interconnectivity, the standard file structure and the
- Xspecific object formats must all be general and extensible. Think
- Xahead when designing an object. It should serve many purposes and
- Xallow many programs to store and read back all the information they
- Xneed; even squeeze in custom data. Then a programmer can store the
- Xavailable data and is encouraged to include fixed contextual details.
- XRecipient programs can read the needed parts, skip unrecognized stuff,
- Xdefault missing data, and use the stored context to help transform
- Xthe data as needed.
- X
- XScope
- X
- XIFF addresses these needs by defining a standard file structure, some
- Xinitial data object types, ways to define new types, and rules for
- Xaccessing these files. We can accomplish a great deal by writing programs
- Xaccording to this standard, but don't expect direct compatibility
- Xwith existing software. We'll need conversion programs to bridge the
- Xgap from the old world.
- X
- XIFF is geared for computers that readily process information in 8-bit
- Xbytes. It assumes a "physical layer" of data storage and transmission
- Xthat reliably maintains "files" as strings of 8-bit bytes. The standard
- Xtreats a "file" as a container of data bytes and is independent of
- Xhow to find a file and whether it has a byte count.
- X
- XThis standard does not by itself implement a clipboard for cutting
- Xand pasting data between programs. A clipboard needs software to mediate
- Xaccess, to maintain a "contents version number" so programs can detect
- Xupdates, and to manage the data in "virtual memory".
- X
- XData Abstraction
- X
- XThe basic problem is how to represent information in a way that's
- Xprogram-independent, compiler- independent, machine-independent, and
- Xdevice-independent.
- X
- XThe computer science approach is "data abstraction", also known as
- X"objects", "actors", and "abstract data types". A data abstraction
- Xhas a "concrete representation" (its storage format), an "abstract
- Xrepresentation" (its capabilities and uses), and access procedures
- Xthat isolate all the calling software from the concrete representation.
- XOnly the access procedures touch the data storage. Hiding mutable
- Xdetails behind an interface is called "information hiding". What data
- Xabstraction does is abstract from details of implementing the object,
- Xnamely the selected storage representation and algorithms for manipulating
- Xit.
- X
- XThe power of this approach is modularity. By adjusting the access
- Xprocedures we can extend and restructure the data without impacting
- Xthe interface or its callers. Conversely, we can extend and restructure
- Xthe interface and callers without making existing data obsolete. It's
- Xgreat for interchange!
- X
- XBut we seem to need the opposite: fixed file formats for all programs
- Xto access. Actually, we could file data abstractions ("filed objects")
- Xby storing the data and access procedures together. We'd have to encode
- Xthe access procedures in a standard machine-independent programming
- Xlanguage la PostScript. Even still, the interface can't evolve freely
- Xsince we can't update all copies of the access procedures. So we'll
- Xhave to design our abstract representations for limited evolution
- Xand occasional revolution (conversion).
- X
- XIn any case, today's microcomputers can't practically store data abstractions.
- XThey can do the next best thing: store arbitrary types of data in
- X"data chunks", each with a type identifier and a length count. The
- Xtype identifier is a reference by name to the access procedures (any
- Xlocal implementation). The length count enables storage-level object
- Xoperations like "copy" and "skip to next" independent of object type.
- X
- XChunk writing is straightforward. Chunk reading requires a trivial
- Xparser to scan each chunk and dispatch to the proper access/conversion
- Xprocedure. Reading chunks nested inside other chunks requires recursion,
- Xbut no lookahead or backup.
- X
- XThat's the main idea of IFF. There are, of course, a few other detailsI
- X
- XPrevious Work
- X
- XWhere our needs are similar, we borrow from existing standards.
- X
- XOur basic need to move data between independently developed programs
- Xis similar to that addressed by the Apple Macintosh desk scrap or
- X"clipboard" [Inside Macintosh chapter "Scrap Manager"]. The Scrap
- XManager works closely with the Resource Manager, a handy filer and
- Xswapper for data objects (text strings, dialog window templates, pictures,
- XfontsI) including types yet to be designed [Inside Macintosh chapter
- X"Resource Manager"]. The Resource Manager is a kin to Smalltalk's
- Xobject swapper.
- X
- XWe will probably write a Macintosh desk accessory that converts IFF
- Xfiles to and from the Macintosh clipboard for quick and easy interchange
- Xwith programs like MacPaint and Resource Mover.
- X
- XMacintosh uses a simple and elegant scheme of 4-character "identifiers"
- Xto identify resource types, clipboard format types, file types, and
- Xfile creator programs. Alternatives are unique ID numbers assigned
- Xby a central authority or by hierarchical authorities, unique ID numbers
- Xgenerated by algorithm, other fixed length character strings, and
- Xvariable length strings. Character string identifiers double as readable
- Xsignposts in data files and programs. The choice of 4 characters is
- Xa good tradeoff between storage space, fetch/compare/store time, and
- Xname space size. We'll honor Apple's designers by adopting this scheme.
- X
- X"PICT" is a good example of a standard structured graphics format
- X(including raster images) and its many uses [Inside Macintosh chapter
- X"QuickDraw"]. Macintosh provides QuickDraw routines in ROM to create,
- Xmanipulate, and display PICTs. Any application can create a PICT by
- Xsimply asking QuickDraw to record a sequence of drawing commands.
- XSince it's just as easy to ask QuickDraw to render a PICT to a screen
- Xor a printer, it's very effective to pass them between programs, say
- Xfrom an illustrator to a word processor. An important feature is the
- Xability to store "comments" in a PICT which QuickDraw will ignore.
- XActually, it passes them to your optional custom "comment handler".
- X
- XPostScript, Adobe's print file standard, is a more general way to
- Xrepresent any print image (which is a specification for putting marks
- Xon paper) [PostScript Language Manual]. In fact, PostScript is a full-fledged
- Xprogramming language. To interpret a PostScript program is to render
- Xa document on a raster output device. The language is defined in layers:
- Xa lexical layer of identifiers, constants, and operators; a layer
- Xof reverse polish semantics including scope rules and a way to define
- Xnew subroutines; and a printing-specific layer of built-in identifiers
- Xand operators for rendering graphic images. It is clearly a powerful
- X(Turing equivalent) image definition language. PICT and a subset of
- XPostScript are candidates for structured graphics standards.
- X
- XA PostScript document can be printed on any raster output device (including
- Xa display) but cannot generally be edited. That's because the original
- Xflexibility and constraints have been discarded. Besides, a PostScript
- Xprogram may use arbitrary computation to supply parameters like placement
- Xand size to each operator. A QuickDraw PICT, in comparison, is a more
- Xrestricted format of graphic primitives parameterized by constants.
- XSo a PICT can be edited at the level of the primitives, e.g. move
- Xor thicken a line. It cannot be edited at the higher level of, say,
- Xthe bar chart data which generated the picture.
- X
- XPostScript has another limitation: Not all kinds of data amount to
- Xmarks on paper. A musical instrument description is one example. PostScript
- Xis just not geared for such uses.
- X
- X"DIF" is another example of data being stored in a general format
- Xusable by future programs [DIF Technical Specification]. DIF is a
- Xformat for spreadsheet data interchange. DIF and PostScript are both
- Xexpressed in plain ASCII text files. This is very handy for printing,
- Xdebugging, experimenting, and transmitting across modems. It can have
- Xsubstantial cost in compaction and read/write work, depending on use.
- XWe won't store IFF files this way but we could define an ASCII alternate
- Xrepresentation with a converter program.
- X
- XInterScript is Xerox' standard for interchange of editable documents
- X[Introduction to InterScript]. It approaches a harder problem: How
- Xto represent editable word processor documents that may contain formatted
- Xtext, pictures, cross-references like figure numbers, and even highly
- Xspecialized objects like mathematical equations? InterScript aims
- Xto define one standard representation for each kind of information.
- XEach InterScript-compatible editor is supposed to preserve the objects
- Xit doesn't understand and even maintain nested cross-references. So
- Xa simple word processor would let you edit the text of a fancy document
- Xwithout discarding the equations or disrupting the equation numbers.
- X
- XOur task is similarly to store high level information and preserve
- Xas much content as practical while moving it between programs. But
- Xwe need to span a larger universe of data types and cannot expect
- Xto centrally define them all. Fortunately, we don't need to make programs
- Xpreserve information that they don't understand. And for better or
- Xworse, we don't have to tackle general-purpose cross-references yet.
- X
- X
- X
- X3. Primitive Data Types
- X
- XAtomic components such as integers and characters that are interpretable
- Xdirectly by the CPU are specified in one format for all processors.
- XWe chose a format that's most convenient for the Motorola MC68000
- Xprocessor [M68000 16/32-Bit Microprocessor Programmer's Reference
- XManual].
- X
- XN.B.: Part 3 dictates the format for "primitive" data types where and
- Xonly where used in the overall file structure and standard kinds of
- Xchunks (Cf. Chunks). The number of such occurrences will be small
- Xenough that the costs of conversion, storage, and management of processor-
- Xspecific files would far exceed the costs of conversion during I/O by "foreign"
- Xprograms. A particular data chunk may be specified with a different
- Xformat for its internal primitive types or with processor- or environment-
- Xspeci fic variants if necessary to optimize local usage. Since that hurts
- Xdata interchange, it's not recommended. (Cf. Designing New Data Sections,
- Xin Part 4.)
- X
- XAlignment
- X
- XAll data objects larger than a byte are aligned on even byte addresses
- Xrelative to the start of the file. This may require padding. Pad bytes
- Xare to be written as zeros, but don't count on that when reading.
- X
- XThis means that every odd-length "chunk" (see below) must be padded
- Xso that the next one will fall on an even boundary. Also, designers
- Xof structures to be stored in chunks should include pad fields where
- Xneeded to align every field larger than a byte. Zeros should be stored
- Xin all the pad bytes.
- X
- XJustification: Even-alignment causes a little extra work for files
- Xthat are used only on certain processors but allows 68000 programs
- Xto construct and scan the data in memory and do block I/O. You just
- Xadd an occasional pad field to data structures that you're going to
- Xblock read/write or else stream read/write an extra byte. And the
- Xsame source code works on all processors. Unspecified alignment, on
- Xthe other hand, would force 68000 programs to (dis)assemble word and
- Xlong-word data one byte at a time. Pretty cumbersome in a high level
- Xlanguage. And if you don't conditionally compile that out for other
- Xprocessors, you won't gain anything.
- X
- XNumbers
- X
- XNumeric types supported are two's complement binary integers in the
- Xformat used by the MC68000 processor high byte first, high word first the
- Xreverse of 8088 and 6502 format. They could potentially include signed
- Xand unsigned 8, 16, and 32 bit integers but the standard only uses
- Xthe following:
- X
- XUBYTE 8 bits unsigned
- XWORD 16 bits signed
- XUWORD 16 bits unsigned
- XLONG 32 bits signed
- X
- XThe actual type definitions depend on the CPU and the compiler. In
- Xthis document, we'll express data type definitions in the C programming
- Xlanguage. [See C, A Reference Manual.] In 68000 Lattice C:
- X
- Xtypedef unsigned char UBYTE; /* 8 bits unsigned */
- Xtypedef short WORD; /* 16 bits signed */
- Xtypedef unsigned short UWORD; /* 16 bits unsigned */
- Xtypedef long LONG; /* 32 bits signed */
- X
- XCharacters
- X
- XThe following character set is assumed wherever characters are used,
- Xe.g. in text strings, IDs, and TEXT chunks (see below).
- X
- XCharacters are encoded in 8-bit ASCII. Characters in the range NUL
- X(hex 0) through DEL (hex 7F) are well defined by the 7-bit ASCII standard.
- XIFF uses the graphic group RJS (SP, hex 20) through R~S (hex 7E).
- X
- XMost of the control character group hex 01 through hex 1F have no
- Xstandard meaning in IFF. The control character LF (hex 0A) is defined
- Xas a "newline" character. It denotes an intentional line break, that
- Xis, a paragraph or line terminator. (There is no way to store an automatic
- Xline break. That is strictly a function of the margins in the environment
- Xthe text is placed.) The control character ESC (hex 1B) is a reserved
- Xescape character under the rules of ANSI standard 3.64-1979 American
- XNational Standard Additional Control Codes for Use with ASCII, ISO
- Xstandard 2022, and ISO/DIS standard 6429.2.
- X
- XCharacters in the range hex 7F through hex FF are not globally defined
- Xin IFF. They are best left reserved for future standardization. But
- Xnote that the FORM type FTXT (formatted text) defines the meaning
- Xof these characters within FTXT forms. In particular, character values
- Xhex 7F through hex 9F are control codes while characters hex A0 through
- Xhex FF are extended graphic characters like , as per the ISO and
- XANSI standards cited above. [See the supplementary document "FTXT"
- XIFF Formatted Text.]
- X
- XDates
- X
- XA "creation date" is defined as the date and time a stream of data
- Xbytes was created. (Some systems call this a "last modified date".)
- XEditing some data changes its creation date. Moving the data between
- Xvolumes or machines does not.
- X
- XThe IFF standard date format will be one of those used in MS-DOS,
- XMacintosh, or Amiga DOS (probably a 32-bit unsigned number of seconds
- Xsince a reference point). Issue: Investigate these three.
- X
- XType IDs
- X
- XA "type ID", "property name", "FORM type", or any other IFF identifier
- Xis a 32-bit value: the concatenation of four ASCII characters in the
- Xrange R S (SP, hex 20) through R~S (hex 7E). Spaces (hex 20) should
- Xnot precede printing characters; trailing spaces are ok. Control characters
- Xare forbidden.
- X
- Xtypedef CHAR ID[4];
- X
- XIDs are compared using a simple 32-bit case-dependent equality test.
- X
- XData section type IDs (aka FORM types) are restriced IDs. (Cf. Data
- XSections.) Since they may be stored in filename extensions (Cf. Single
- XPurpose Files) lower case letters and punctuation marks are forbidden.
- XTrailing spaces are ok.
- X
- XCarefully choose those four characters when you pick a new ID. Make
- Xthem mnemonic so programmers can look at an interchange format file
- Xand figure out what kind of data it contains. The name space makes
- Xit possible for developers scattered around the globe to generate
- XID values with minimal collisions so long as they choose specific
- Xnames like "MUS4" instead of general ones like "TYPE" and "FILE".
- XEA will "register" new FORM type IDs and format descriptions as they're
- Xdevised, but collisions will be improbable so there will be no pressure
- Xon this "clearinghouse" process. Appendix A has a list of currently
- Xdefined IDs.
- X
- XSometimes it's necessary to make data format changes that aren't backward
- Xcompatible. Since IDs are used to denote data formats in IFF, new
- XIDs are chosen to denote revised formats. Since programs won't read
- Xchunks whose IDs they don't recognize (see Chunks, below), the new
- XIDs keep old programs from stumbling over new data. The conventional
- Xway to chose a "revision" ID is to increment the last character if
- Xit's a digit or else change the last character to a digit. E.g. first
- Xand second revisions of the ID "XY" would be "XY1" and "XY2". Revisions
- Xof "CMAP" would be "CMA1" and "CMA2".
- X
- XChunks
- X
- XChunks are the building blocks in the IFF structure. The form expressed
- Xas a C typedef is:
- X
- Xtypedef struct {
- X ID ckID;
- X LONG ckSize; /* sizeof(ckData) */
- X UBYTE ckData[/* ckSize */];
- X } Chunk;
- X
- XWe can diagram an example chunk a "CMAP" chunk containing 12 data
- Xbytes like this:
- X ----------------
- X ckID: | 'CMAP' |
- X ckSize: | 12 |
- X ckData: | 0, 0, 0, 32 | --------
- X | 0, 0, 64, 0 | 12 bytes
- X | 0, 0, 64, 0 | ---------
- X ----------------
- X
- XThe fixed header part means "Here's a type ckID chunk with ckSize
- Xbytes of data."
- X
- XThe ckID identifies the format and purpose of the chunk. As a rule,
- Xa program must recognize ckID to interpret ckData. It should skip
- Xover all unrecognized chunks. The ckID also serves as a format version
- Xnumber as long as we pick new IDs to identify new formats of ckData
- X(see above).
- X
- XThe following ckIDs are universally reserved to identify chunks with
- Xparticular IFF meanings: "LIST", "FORM", "PROP", "CAT ", and "
- X". The special ID " " (4 spaces) is a ckID for "filler" chunks,
- Xthat is, chunks that fill space but have no meaningful contents. The
- XIDs "LIS1" through "LIS9", "FOR1" through "FOR9", and "CAT1" through
- X"CAT9" are reserved for future "version number" variations. All IFF-compatible
- Xsoftware must account for these 23 chunk IDs. Appendix A has a list
- Xof predefined IDs.
- X
- XThe ckSize is a logical block size how many data bytes are in ckData.
- XIf ckData is an odd number of bytes long, a 0 pad byte follows which
- Xis not included in ckSize. (Cf. Alignment.) A chunk's total physical
- Xsize is ckSize rounded up to an even number plus the size of the header.
- XSo the smallest chunk is 8 bytes long with ckSize = 0. For the sake
- Xof following chunks, programs must respect every chunk's ckSize as
- Xa virtual end-of-file for reading its ckData even if that data is
- Xmalformed, e.g. if nested contents are truncated.
- X
- XWe can describe the syntax of a chunk as a regular expression with
- X"#" representing the ckSize, i.e. the length of the following {braced}
- Xbytes. The "[0]" represents a sometimes needed pad byte. (The regular
- Xexpressions in this document are collected in Appendix A along with
- Xan explanation of notation.)
- X
- XChunk ::= ID #{ UBYTE* } [0]
- X
- XOne chunk output technique is to stream write a chunk header, stream
- Xwrite the chunk contents, then random access back to the header to
- Xfill in the size. Another technique is to make a preliminary pass
- Xover the data to compute the size, then write it out all at once.
- X
- XStrings, String Chunks, and String Properties
- X
- XIn a string of ASCII text, LF denotes a forced line break (paragraph
- Xor line terminator). Other control characters are not used. (Cf. Characters.)
- X
- XThe ckID for a chunk that contains a string of plain, unformatted
- Xtext is "TEXT". As a practical matter, a text string should probably
- Xnot be longer than 32767 bytes. The standard allows up to 231 - 1
- Xbytes.
- X
- XWhen used as a data property (see below), a text string chunk may
- Xbe 0 to 255 characters long. Such a string is readily converted to
- Xa C string or a Pascal STRING[255]. The ckID of a property must be
- Xthe property name, not "TEXT".
- X
- XWhen used as a part of a chunk or data property, restricted C string
- Xformat is normally used. That means 0 to 255 characters followed by
- Xa NUL byte (ASCII value 0).
- X
- XData Properties
- X
- XData properties specify attributes for following (non-property) chunks.
- XA data property essentially says "identifier = value", for example
- X"XY = (10, 200)", telling something about following chunks. Properties
- Xmay only appear inside data sections ("FORM" chunks, cf. Data Sections)
- Xand property sections ("PROP" chunks, cf. Group PROP).
- X
- XThe form of a data property is a special case of Chunk. The ckID is
- Xa property name as well as a property type. The ckSize should be small
- Xsince data properties are intended to be accumulated in RAM when reading
- Xa file. (256 bytes is a reasonable upper bound.) Syntactically:
- X
- XProperty ::= Chunk
- X
- XWhen designing a data object, use properties to describe context information
- Xlike the size of an image, even if they don't vary in your program.
- XOther programs will need this information.
- X
- XThink of property settings as assignments to variables in a programming
- Xlanguage. Multiple assignments are redundant and local assignments
- Xtemporarily override global assignments. The order of assignments
- Xdoesn't matter as long as they precede the affected chunks. (Cf. LISTs,
- XCATs, and Shared Properties.)
- X
- XEach object type (FORM type) is a local name space for property IDs.
- XThink of a "CMAP" property in a "FORM ILBM" as the qualified ID "ILBM.CMAP".
- XProperty IDs specified when an object type is designed (and therefore
- Xknown to all clients) are called "standard" while specialized ones
- Xadded later are "nonstandard".
- X
- XLinks
- X
- XIssue: A standard mechanism for "links" or "cross references" is very
- Xdesirable for things like combining images and sounds into animations.
- XPerhaps we'll define "link" chunks within FORMs that refer to other
- XFORMs or to specific chunks within the same and other FORMs. This
- Xneeds further work. EA IFF 1985 has no standard link mechanism.
- X
- XFor now, it may suffice to read a list of, say, musical instruments,
- Xand then just refer to them within a musical score by index number.
- X
- XFile References
- X
- XIssue: We may need a standard form for references to other files.
- XA "file ref" could name a directory and a file in the same type of
- Xoperating system as the ref's originator. Following the reference
- Xwould expect the file to be on some mounted volume. In a network environment,
- Xa file ref could name a server, too.
- X
- XIssue: How can we express operating-system independent file refs?
- X
- XIssue: What about a means to reference a portion of another file?
- XWould this be a "file ref" plus a reference to a "link" within the
- Xtarget file?
- X
- X
- X
- X4. Data Sections
- X
- XThe first thing we need of a file is to check: Does it contain IFF
- Xdata and, if so, does it contain the kind of data we're looking for?
- XSo we come to the notion of a "data section".
- X
- XA "data section" or IFF "FORM" is one self-contained "data object"
- Xthat might be stored in a file by itself. It is one high level data
- Xobject such as a picture or a sound effect. The IFF structure "FORM"
- Xmakes it self- identifying. It could be a composite object like a
- Xmusical score with nested musical instrument descriptions.
- X
- XGroup FORM
- X
- XA data section is a chunk with ckID "FORM" and this arrangement:
- X
- XFORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)*
- X}
- XFormType ::= ID
- XLocalChunk ::= Property | Chunk
- X
- XThe ID "FORM" is a syntactic keyword like "struct" in C. Think of
- Xa "struct ILBM" containing a field "CMAP". If you see "FORM" you'll
- Xknow to expect a FORM type ID (the structure name, "ILBM" in this
- Xexample) and a particular contents arrangement or "syntax" (local
- Xchunks, FORMs, LISTs, and CATs). (LISTs and CATs are discussed in
- Xpart 5, below.) A "FORM ILBM", in particular, might contain a local
- Xchunk "CMAP", an "ILBM.CMAP" (to use a qualified name).
- X
- XSo the chunk ID "FORM" indicates a data section. It implies that the
- Xchunk contains an ID and some number of nested chunks. In reading
- Xa FORM, like any other chunk, programs must respect its ckSize as
- Xa virtual end-of-file for reading its contents, even if they're truncated.
- X
- XThe FormType (or FORM type) is a restricted ID that may not contain
- Xlower case letters or punctuation characters. (Cf. Type IDs. Cf. Single
- XPurpose Files.)
- X
- XThe type-specific information in a FORM is composed of its "local
- Xchunks": data properties and other chunks. Each FORM type is a local
- Xname space for local chunk IDs. So "CMAP" local chunks in other FORM
- Xtypes may be unrelated to "ILBM.CMAP". More than that, each FORM type
- Xdefines semantic scope. If you know what a FORM ILBM is, you'll know
- Xwhat an ILBM.CMAP is.
- X
- XLocal chunks defined when the FORM type is designed (and therefore
- Xknown to all clients of this type) are called "standard" while specialized
- Xones added later are "nonstandard".
- X
- XAmong the local chunks, property chunks give settings for various
- Xdetails like text font while the other chunks supply the essential
- Xinformation. This distinction is not clear cut. A property setting
- Xcancelled by a later setting of the same property has effect only
- Xon data chunks in between. E.g. in the sequence:
- X
- Xprop1 = x (propN = value)* prop1 = y
- X
- Xwhere the propNs are not prop1, the setting prop1 = x has no effect.
- X
- XThe following universal chunk IDs are reserved inside any FORM: "LIST",
- X"FORM", "PROP", "CAT ", "JJJJ", "LIS1" through "LIS9", "FOR1" through
- X"FOR9", and "CAT1" through "CAT9". (Cf. Chunks. Cf. Group LIST. Cf.
- XGroup PROP.) For clarity, these universal chunk names may not be FORM
- Xtype IDs, either.
- X
- XPart 5, below, talks about grouping FORMs into LISTs and CATs. They
- Xlet you group a bunch of FORMs but don't impose any particular meaning
- Xor constraints on the grouping. Read on.
- X
- XComposite FORMs
- X
- XA FORM chunk inside a FORM is a full-fledged data section. This means
- Xyou can build a composite object like a multi-frame animation sequence
- Xfrom available picture FORMs and sound effect FORMs. You can insert
- Xadditional chunks with information like frame rate and frame count.
- X
- XUsing composite FORMs, you leverage on existing programs that create
- Xand edit the component FORMs. Those editors may even look into your
- Xcomposite object to copy out its type of component, although it'll
- Xbe the rare program that's fancy enough to do that. Such editors are
- Xnot allowed to replace their component objects within your composite
- Xobject. That's because the IFF standard lets you specify consistency
- Xrequirements for the composite FORM such as maintaining a count or
- Xa directory of the components. Only programs that are written to uphold
- Xthe rules of your FORM type should create or modify such FORMs.
- X
- XTherefore, in designing a program that creates composite objects,
- Xyou are strongly requested to provide a facility for your users to
- Ximport and export the nested FORMs. Import and export could move the
- Xdata through a clipboard or a file.
- X
- XHere are several existing FORM types and rules for defining new ones.
- X
- XFTXT
- X
- XAn FTXT data section contains text with character formatting information
- Xlike fonts and faces. It has no paragraph or document formatting information
- Xlike margins and page headers. FORM FTXT is well matched to the text
- Xrepresentation in Amiga's Intuition environment. See the supplemental
- Xdocument "FTXT" IFF Formatted Text.
- X
- XILBM
- X
- X"ILBM" is an InterLeaved BitMap image with color map; a machine-independent
- Xformat for raster images. FORM ILBM is the standard image file format
- Xfor the Commodore-Amiga computer and is useful in other environments,
- Xtoo. See the supplemental document "ILBM" IFF Interleaved Bitmap.
- X
- XPICS
- X
- XThe data chunk inside a "PICS" data section has ID "PICT" and holds
- Xa QuickDraw picture. Issue: Allow more than one PICT in a PICS? See
- XInside Macintosh chapter "QuickDraw" for details on PICTs and how
- Xto create and display them on the Macintosh computer.
- X
- XThe only standard property for PICS is "XY", an optional property
- Xthat indicates the position of the PICT relative to "the big picture".
- XThe contents of an XY is a QuickDraw Point.
- X
- XNote: PICT may be limited to Macintosh use, in which case there'll
- Xbe another format for structured graphics in other environments.
- X
- XOther Macintosh Resource Types
- X
- XSome other Macintosh resource types could be adopted for use within
- XIFF files; perhaps MWRT, ICN, ICN#, and STR#.
- X
- XIssue: Consider the candidates and reserve some more IDs.
- X
- XDesigning New Data Sections
- X
- XSupplemental documents will define additional object types. A supplement
- Xneeds to specify the object's purpose, its FORM type ID, the IDs and
- Xformats of standard local chunks, and rules for generating and interpreting
- Xthe data. It's a good idea to supply typedefs and an example source
- Xprogram that accesses the new object. See "ILBM" IFF Interleaved Bitmap
- Xfor a good example.
- X
- XAnyone can pick a new FORM type ID but should reserve it with Electronic
- XArts at their earliest convenience. [Issue: EA contact person? Hand
- Xthis off to another organization?] While decentralized format definitions
- Xand extensions are possible in IFF, our preference is to get design
- Xconsensus by committee, implement a program to read and write it,
- Xperhaps tune the format, and then publish the format with example
- Xcode. Some organization should remain in charge of answering questions
- Xand coordinating extensions to the format.
- X
- XIf it becomes necessary to revise the design of some data section,
- Xits FORM type ID will serve as a version number (Cf. Type IDs). E.g.
- Xa revised "VDEO" data section could be called "VDE1". But try to get
- Xby with compatible revisions within the existing FORM type.
- X
- XIn a new FORM type, the rules for primitive data types and word-alignment
- X(Cf. Primitive Data Types) may be overriden for the contents of its
- Xlocal chunks but not for the chunk structure itself if your documentation
- Xspells out the deviations. If machine-specific type variants are needed,
- Xe.g. to store vast numbers of integers in reverse bit order, then
- Xoutline the conversion algorithm and indicate the variant inside each
- Xfile, perhaps via different FORM types. Needless to say, variations
- Xshould be minimized.
- X
- XIn designing a FORM type, encapsulate all the data that other programs
- Xwill need to interpret your files. E.g. a raster graphics image should
- Xspecify the image size even if your program always uses 320 x 200
- Xpixels x 3 bitplanes. Receiving programs are then empowered to append
- Xor clip the image rectangle, to add or drop bitplanes, etc. This enables
- Xa lot more compatibility.
- X
- XSeparate the central data (like musical notes) from more specialized
- Xinformation (like note beams) so simpler programs can extract the
- Xcentral parts during read-in. Leave room for expansion so other programs
- Xcan squeeze in new kinds of information (like lyrics). And remember
- Xto keep the property chunks manageably short let's say 2 256 bytes.
- X
- XWhen designing a data object, try to strike a good tradeoff between
- Xa super-general format and a highly-specialized one. Fit the details
- Xto at least one particular need, for example a raster image might
- Xas well store pixels in the current machine's scan order. But add
- Xthe kind of generality that makes it usable with foreseeable hardware
- Xand software. E.g. use a whole byte for each red, green, and blue
- Xcolor value even if this year's computer has only 4-bit video DACs.
- XThink ahead and help other programs so long as the overhead is acceptable.
- XE.g. run compress a raster by scan line rather than as a unit so future
- Xprograms can swap images by scan line to and from secondary storage.
- X
- XTry to design a general purpose "least common multiple" format that
- Xencompasses the needs of many programs without getting too complicated.
- XLet's coalesce our uses around a few such formats widely separated
- Xin the vast design space. Two factors make this flexibility and simplicity
- Xpractical. First, file storage space is getting very plentiful, so
- Xcompaction is not a priority. Second, nearly any locally-performed
- Xdata conversion work during file reading and writing will be cheap
- Xcompared to the I/O time.
- X
- XIt must be ok to copy a LIST or FORM or CAT intact, e.g. to incorporate
- Xit into a composite FORM. So any kind of internal references within
- Xa FORM must be relative references. They could be relative to the
- Xstart of the containing FORM, relative from the referencing chunk,
- Xor a sequence number into a collection.
- X
- XWith composite FORMs, you leverage on existing programs that create
- Xand edit the components. If you write a program that creates composite
- Xobjects, please provide a facility for your users to import and export
- Xthe nested FORMs. The import and export functions may move data through
- Xa separate file or a clipboard.
- X
- XFinally, don't forget to specify all implied rules in detail.
- X
- X
- X
- X5. LISTs, CATs, and Shared Properties
- X
- XData often needs to be grouped together like a list of icons. Sometimes
- Xa trick like arranging little images into a big raster works, but
- Xgenerally they'll need to be structured as a first class group. The
- Xobjects "LIST" and "CAT" are IFF-universal mechanisms for this purpose.
- X
- XProperty settings sometimes need to be shared over a list of similar
- Xobjects. E.g. a list of icons may share one color map. LIST provides
- Xa means called "PROP" to do this. One purpose of a LIST is to define
- Xthe scope of a PROP. A "CAT", on the other hand, is simply a concatenation
- Xof objects.
- X
- XSimpler programs may skip LISTs and PROPs altogether and just handle
- XFORMs and CATs. All "fully-conforming" IFF programs also know about
- X"CAT ", "LIST", and "PROP". Any program that reads a FORM inside a
- XLIST must process shared PROPs to correctly interpret that FORM.
- X
- XGroup CAT
- X
- XA CAT is just an untyped group of data objects.
- X
- XStructurally, a CAT is a chunk with chunk ID "CAT " containing a "contents
- Xtype" ID followed by the nested objects. The ckSize of each contained
- Xchunk is essentially a relative pointer to the next one.
- X
- XCAT ::= "CAT " #{ ContentsType (FORM | LIST | CAT)* }
- XContentsType ::= ID -- a hint or an "abstract data type" ID
- X
- XIn reading a CAT, like any other chunk, programs must respect it's
- XckSize as a virtual end-of-file for reading the nested objects even
- Xif they're malformed or truncated.
- X
- XThe "contents type" following the CAT's ckSize indicates what kind
- Xof FORMs are inside. So a CAT of ILBMs would store "ILBM" there. It's
- Xjust a hint. It may be used to store an "abstract data type". A CAT
- Xcould just have blank contents ID ("JJJJ") if it contains more than
- Xone kind of FORM.
- X
- XCAT defines only the format of the group. The group's meaning is open
- Xto interpretation. This is like a list in LISP: the structure of cells
- Xis predefined but the meaning of the contents as, say, an association
- Xlist depends on use. If you need a group with an enforced meaning
- X(an "abstract data type" or Smalltalk "subclass"), some consistency
- Xconstraints, or additional data chunks, use a composite FORM instead
- X(Cf. Composite FORMs).
- X
- XSince a CAT just means a concatenation of objects, CATs are rarely
- Xnested. Programs should really merge CATs rather than nest them.
- X
- XGroup LIST
- X
- XA LIST defines a group very much like CAT but it also gives a scope
- Xfor PROPs (see below). And unlike CATs, LISTs should not be merged
- Xwithout understanding their contents.
- X
- XStructurally, a LIST is a chunk with ckID "LIST" containing a "contents
- Xtype" ID, optional shared properties, and the nested contents (FORMs,
- XLISTs, and CATs), in that order. The ckSize of each contained chunk
- Xis a relative pointer to the next one. A LIST is not an arbitrary
- Xlinked list the cells are simply concatenated.
- X
- XLIST ::= "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* }
- XContentsType ::= ID
- X
- XGroup PROP
- X
- XPROP chunks may appear in LISTs (not in FORMs or CATs). They supply
- Xshared properties for the FORMs in that LIST. This ability to elevate
- Xsome property settings to shared status for a list of forms is useful
- Xfor both indirection and compaction. E.g. a list of images with the
- Xsame size and colors can share one "size" property and one "color
- Xmap" property. Individual FORMs can override the shared settings.
- X
- XThe contents of a PROP is like a FORM with no data chunks:
- X
- XPROP ::= "PROP" #{ FormType Property* }
- X
- XIt means, "Here are the shared properties for FORM type <<FormType>."
- X
- XA LIST may have at most one PROP of a FORM type, and all the PROPs
- Xmust appear before any of the FORMs or nested LISTs and CATs. You
- Xcan have subsequences of FORMs sharing properties by making each subsequence
- Xa LIST.
- X
- XScoping: Think of property settings as variable bindings in nested
- Xblocks of a programming language. Where in C you could write:
- X
- XTEXT_FONT text_font = Courier; /* program's global default */
- X
- XFile(); {
- X TEXT_FONT text_font = TimesRoman; /* shared setting */
- X
- X {
- X TEXT_FONT text_font = Helvetica; /* local setting */
- X Print("Hello "); /* uses font Helvetica */
- X }
- X
- X {
- X Print("there."); /* uses font TimesRoman */
- X }
- X }
- X
- XAn IFF file could contain:
- X
- XLIST {
- X PROP TEXT {
- X FONT {TimesRoman} /* shared setting */
- X }
- X
- X FORM TEXT {
- X FONT {Helvetica} /* local setting */
- X CHRS {Hello } /* uses font Helvetica */
- X }
- X
- X FORM TEXT {
- X CHRS {there.} /* uses font TimesRoman */
- X }
- X }
- X
- XThe shared property assignments selectively override the reader's
- Xglobal defaults, but only for FORMs within the group. A FORM's own
- Xproperty assignments selectively override the global and group-supplied
- Xvalues. So when reading an IFF file, keep property settings on a stack.
- XThey're designed to be small enough to hold in main memory.
- X
- XShared properties are semantically equivalent to copying those properties
- Xinto each of the nested FORMs right after their FORM type IDs.
- X
- XProperties for LIST
- X
- XOptional "properties for LIST" store the origin of the list's contents
- Xin a PROP chunk for the fake FORM type "LIST". They are the properties
- Xoriginating program "OPGM", processor family "OCPU", computer type
- X"OCMP", computer serial number or network address "OSN ", and user
- Xname "UNAM". In our imperfect world, these could be called upon to
- Xdistinguish between unintended variations of a data format or to work
- Xaround bugs in particular originating/receiving program pairs. Issue:
- XSpecify the format of these properties.
- X
- XA creation date could also be stored in a property but let's ask that
- Xfile creating, editing, and transporting programs maintain the correct
- Xdate in the local file system. Programs that move files between machine
- Xtypes are expected to copy across the creation dates.
- X
- X
- X
- X6. Standard File Structure
- X
- XFile Structure Overview
- X
- XAn IFF file is just a single chunk of type FORM, LIST, or CAT. Therefore
- Xan IFF file can be recognized by its first 4 bytes: "FORM", "LIST",
- Xor "CAT ". Any file contents after the chunk's end are to be ignored.
- X
- XSince an IFF file can be a group of objects, programs that read/write
- Xsingle objects can communicate to an extent with programs that read/write
- Xgroups. You're encouraged to write programs that handle all the objects
- Xin a LIST or CAT. A graphics editor, for example, could process a
- Xlist of pictures as a multiple page document, one page at a time.
- X
- XPrograms should enforce IFF's syntactic rules when reading and writing
- Xfiles. This ensures robust data transfer. The public domain IFF reader/writer
- Xsubroutine package does this for you. A utility program "IFFCheck"
- Xis available that scans an IFF file and checks it for conformance
- Xto IFF's syntactic rules. IFFCheck also prints an outline of the chunks
- Xin the file, showing the ckID and ckSize of each. This is quite handy
- Xwhen building IFF programs. Example programs are also available to
- Xshow details of reading and writing IFF files.
- X
- XA merge program "IFFJoin" will be available that logically appends
- XIFF files into a single CAT group. It "unwraps" each input file that
- Xis a CAT so that the combined file isn't nested CATs.
- X
- XIf we need to revise the IFF standard, the three anchoring IDs will
- Xbe used as "version numbers". That's why IDs "FOR1" through "FOR9",
- X"LIS1" through "LIS9", and "CAT1" through "CAT9" are reserved.
- X
- XIFF formats are designed for reasonable performance with floppy disks.
- XWe achieve considerable simplicity in the formats and programs by
- Xrelying on the host file system rather than defining universal grouping
- Xstructures like directories for LIST contents. On huge storage systems,
- XIFF files could be leaf nodes in a file structure like a B-tree. Let's
- Xhope the host file system implements that for us!
- X
- XThre are two kinds of IFF files: single purpose files and scrap files.
- XThey differ in the interpretation of multiple data objects and in
- Xthe file's external type.
- X
- XSingle Purpose Files
- X
- XA single purpose IFF file is for normal "document" and "archive" storage.
- XThis is in contrast with "scrap files" (see below) and temporary backing
- Xstorage (non-interchange files).
- X
- XThe external file type (or filename extension, depending on the host
- Xfile system) indicates the file's contents. It's generally the FORM
- Xtype of the data contained, hence the restrictions on FORM type IDs.
- X
- XProgrammers and users may pick an "intended use" type as the filename
- Xextension to make it easy to filter for the relevant files in a filename
- Xrequestor. This is actually a "subclass" or "subtype" that conveniently
- Xseparates files of the same FORM type that have different uses. Programs
- Xcannot demand conformity to its expected subtypes without overly restricting
- Xdata interchange since they cannot know about the subtypes to be used
- Xby future programs that users will want to exchange data with.
- X
- XIssue: How to generate 3-letter MS-DOS extensions from 4-letter FORM
- Xtype IDs?
- X
- XMost single purpose files will be a single FORM (perhaps a composite
- XFORM like a musical score containing nested FORMs like musical instrument
- Xdescriptions). If it's a LIST or a CAT, programs should skip over
- Xunrecognized objects to read the recognized ones or the first recognized
- Xone. Then a program that can read a single purpose file can read something
- Xout of a "scrap file", too.
- X
- XScrap Files
- X
- XA "scrap file" is for maximum interconnectivity in getting data between
- Xprograms; the core of a clipboard function. Scrap files may have type
- X"IFF " or filename extension ".IFF".
- X
- XA scrap file is typically a CAT containing alternate representations
- Xof the same basic information. Include as many alternatives as you
- Xcan readily generate. This redundancy improves interconnectivity in
- Xsituations where we can't make all programs read and write super-general
- Xformats. [Inside Macintosh chapter "Scrap Manager".] E.g. a graphically-
- Xannotated musical score might be supplemented by a stripped down 4-voice
- Xmelody and by a text (the lyrics).
- X
- XThe originating program should write the alternate representations
- Xin order of "preference": most preferred (most comprehensive) type
- Xto least preferred (least comprehensive) type. A receiving program
- Xshould either use the first appearing type that it understands or
- Xsearch for its own "preferred" type.
- X
- XA scrap file should have at most one alternative of any type. (A LIST
- Xof same type objects is ok as one of the alternatives.) But don't
- Xcount on this when reading; ignore extra sections of a type. Then
- Xa program that reads scrap files can read something out of single
- Xpurpose files.
- X
- XRules for Reader Programs
- X
- XHere are some notes on building programs that read IFF files. If you
- Xuse the standard IFF reader module "IFFR.C", many of these rules and
- Xdetails will be automatically handled. (See "Support Software" in
- XAppendix A.) We recommend that you start from the example program
- X"ShowILBM.C". You should also read up on recursive descent parsers.
- X[See, for example, Compiler Construction, An Advanced Course.]
- X
- X% The standard is very flexible so many programs can exchange
- Xdata. This implies a program has to scan the file and react to what's
- Xactually there in whatever order it appears. An IFF reader program
- Xis a parser.
- X
- X% For interchange to really work, programs must be willing to
- Xdo some conversion during read-in. If the data isn't exactly what
- Xyou expect, say, the raster is smaller than those created by your
- Xprogram, then adjust it. Similarly, your program could crop a large
- Xpicture, add or drop bitplanes, and create/discard a mask plane. The
- Xprogram should give up gracefully on data that it can't convert.
- X
- X% If it doesn't start with "FORM", "LIST", or "CAT ", it's not
- Xan IFF-85 file.
- X
- X% For any chunk you encounter, you must recognize its type ID
- Xto understand its contents.
- X
- X% For any FORM chunk you encounter, you must recognize its FORM
- Xtype ID to understand the contained "local chunks". Even if you don't
- Xrecognize the FORM type, you can still scan it for nested FORMs, LISTs,
- Xand CATs of interest.
- X
- X% Don't forget to skip the pad byte after every odd-length chunk.
- X
- X% Chunk types LIST, FORM, PROP, and CAT are generic groups. They
- Xalways contain a subtype ID followed by chunks.
- X
- X% Readers ought to handle a CAT of FORMs in a file. You may treat
- Xthe FORMs like document pages to sequence through or just use the
- Xfirst FORM.
- X
- X% Simpler IFF readers completely skip LISTs. "Fully IFF-conforming"
- Xreaders are those that handle LISTs, even if just to read the first
- XFORM from a file. If you do look into a LIST, you must process shared
- Xproperties (in PROP chunks) properly. The idea is to get the correct
- Xdata or none at all.
- X
- X% The nicest readers are willing to look into unrecognized FORMs
- Xfor nested FORM types that they do recognize. For example, a musical
- Xscore may contain nested instrument descriptions and an animation
- Xfile may contain still pictures.
- X
- XNote to programmers: Processing PROP chunks is not simple! You'll
- Xneed some background in interpreters with stack frames. If this is
- Xforeign to you, build programs that read/write only one FORM per file.
- XFor the more intrepid programmers, the next paragraph summarizes how
- Xto process LISTs and PROPs. See the general IFF reader module "IFFR.C"
- Xand the example program "ShowILBM.C" for details.
- X
- XAllocate a stack frame for every LIST and FORM you encounter and initialize
- Xit by copying the stack frame of the parent LIST or FORM. At the top
- Xlevel, you'll need a stack frame initialized to your program's global
- Xdefaults. While reading each LIST or FORM, store all encountered properties
- Xinto the current stack frame. In the example ShowILBM, each stack
- Xframe has a place for a bitmap header property ILBM.BMHD and a color
- Xmap property ILBM.CMAP. When you finally get to the ILBM's BODY chunk,
- Xuse the property settings accumulated in the current stack frame.
- X
- XAn alternate implementation would just remember PROPs encountered,
- Xforgetting each on reaching the end of its scope (the end of the containing
- XLIST). When a FORM XXXX is encountered, scan the chunks in all remembered
- XPROPs XXXX, in order, as if they appeared before the chunks actually
- Xin the FORM XXXX. This gets trickier if you read FORMs inside of FORMs.
- X
- XRules for Writer Programs
- X
- XHere are some notes on building programs that write IFF files, which
- Xis much easier than reading them. If you use the standard IFF writer
- Xmodule "IFFW.C" (see "Support Software" in Appendix A), many of these
- Xrules and details will automatically be enforced. See the example
- Xprogram "Raw2ILBM.C".
- X
- X% An IFF file is a single FORM, LIST, or CAT chunk.
- X
- X% Any IFF-85 file must start with the 4 characters "FORM", "LIST",
- Xor "CAT ", followed by a LONG ckSize. There should be no data after
- Xthe chunk end.
- X
- X% Chunk types LIST, FORM, PROP, and CAT are generic. They always
- Xcontain a subtype ID followed by chunks. These three IDs are universally
- Xreserved, as are "LIS1" through "LIS9", "FOR1" through "FOR9", "CAT1"
- Xthrough "CAT9", and " ".
- X
- X% Don't forget to write a 0 pad byte after each odd-length chunk.
- X
- X% Four techniques for writing an IFF group: (1) build the data
- Xin a file mapped into virtual memory, (2) build the data in memory
- Xblocks and use block I/O, (3) stream write the data piecemeal and
- X(don't forget!) random access back to set the group length count,
- Xand (4) make a preliminary pass to compute the length count then stream
- Xwrite the data.
- X
- X% Do not try to edit a file that you don't know how to create.
- XPrograms may look into a file and copy out nested FORMs of types that
- Xthey recognize, but don't edit and replace the nested FORMs and don't
- Xadd or remove them. That could make the containing structure inconsistent.
- XYou may write a new file containing items you copied (or copied and
- Xmodified) from another IFF file, but don't copy structural parts you
- Xdon't understand.
- X
- X% You must adhere to the syntax descriptions in Appendex A. E.g.
- XPROPs may only appear inside LISTs.
- X
- X
- X
- X
- XAppendix A. Reference
- X
- XType Definitions
- X
- XThe following C typedefs describe standard IFF structures. Declarations
- Xto use in practice will vary with the CPU and compiler. For example,
- X68000 Lattice C produces efficient comparison code if we define ID
- Xas a "LONG". A macro "MakeID" builds these IDs at compile time.
- X
- X/* Standard IFF types, expressed in 68000 Lattice C. */
- X
- Xtypedef unsigned char UBYTE; /* 8 bits unsigned */
- Xtypedef short WORD; /* 16 bits signed */
- Xtypedef unsigned short UWORD; /* 16 bits unsigned */
- Xtypedef long LONG; /* 32 bits signed */
- X
- Xtypedef char ID[4]; /* 4 chars in ' ' through '~' */
- X
- Xtypedef struct {
- X ID ckID;
- X LONG ckSize; /* sizeof(ckData) */
- X UBYTE ckData[/* ckSize */];
- X } Chunk;
- X
- X/* ID typedef and builder for 68000 Lattice C. */
- Xtypedef LONG ID; /* 4 chars in ' ' through '~' */
- X#define MakeID(a,b,c,d) ( (a)<<<<24 | (b)<<<<16 | (c)<<<<8 | (d) )
- X
- X/* Globally reserved IDs. */
- X#define ID_FORM MakeID('F','O','R','M')
- X#define ID_LIST MakeID('L','I','S','T')
- X#define ID_PROP MakeID('P','R','O','P')
- X#define ID_CAT MakeID('C','A','T',' ')
- X#define ID_FILLER MakeID(' ',' ',' ',' ')
- X
- XSyntax Definitions
- X
- XHere's a collection of the syntax definitions in this document.
- X
- XChunk ::= ID #{ UBYTE* } [0]
- X
- XProperty ::= Chunk
- X
- XFORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)*
- X}
- XFormType ::= ID
- XLocalChunk ::= Property | Chunk
- X
- XCAT ::= "CAT " #{ ContentsType (FORM | LIST | CAT)* }
- XContentsType ::= ID -- a hint or an "abstract data type" ID
- X
- XLIST ::= "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* }
- XPROP ::= "PROP" #{ FormType Property* }
- X
- XIn this extended regular expression notation, the token "#" represents
- Xa ckSize LONG count of the following {braced} data bytes. Literal
- Xitems are shown in "quotes", [square bracketed items] are optional,
- Xand "*" means 0 or more instances. A sometimes-needed pad byte is
- Xshown as "[0]".
- X
- XDefined Chunk IDs
- X
- XThis is a table of currently defined chunk IDs. We may also borrow
- Xsome Macintosh IDs and data formats.
- X
- XGroup chunk IDs
- X FORM, LIST, PROP, CAT.
- XFuture revision group chunk IDs
- X FOR1 I FOR9, LIS1 I LIS9, CAT1 I CAT9.
- XFORM type IDs
- X (The above group chunk IDs may not be used for FORM type IDs.)
- X (Lower case letters and punctuation marks are forbidden in FORM
- Xtype IDs.)
- X 8SVX 8-bit sampled sound voice, ANBM animated bitmap, FNTR raster
- Xfont, FNTV vector font, FTXT formatted text, GSCR general-use musical
- Xscore, ILBM interleaved raster bitmap image, PDEF Deluxe Print page
- Xdefinition, PICS Macintosh picture, PLBM (obsolete), USCR Uhuru Sound
- XSoftware musical score, UVOX Uhuru Sound Software Macintosh voice,
- XSMUS simple musical score, VDEO Deluxe Video Construction Set video.
- XData chunk IDs
- X "JJJJ", TEXT, PICT.
- XPROP LIST property IDs
- X OPGM, OCPU, OCMP, OSN, UNAM.
- X
- X
- X
- XSupport Software
- X
- XThese public domain C source programs are available for use in building
- XIFF-compatible programs:
- X
- XIFF.H, IFFR.C, IFFW.C
- X
- X IFF reader and writer package.
- X These modules handle many of the details of reliably
- X reading and writing IFF files.
- X
- XIFFCheck.C This handy utility program scans an IFF file, checks
- X that the contents are well formed, and prints an outline
- X of the chunks.
- X
- XPACKER.H, Packer.C, UnPacker.C
- X
- X Run encoder and decoder used for ILBM files.
- X
- XILBM.H, ILBMR.C, ILBMW.C
- X
- X Reader and writer support routines for raster image
- X FORM ILBM. ILBMR calls IFFR and UnPacker. ILBMW calls
- X IFFW and Packer.
- X
- XShowILBM.C
- X Example caller of IFFR and ILBMR modules. This
- X Commodore-Amiga program reads and displays a FORM ILBM.
- XRaw2ILBM.C
- X Example ILBM writer program. As a demonstration, it
- X reads a raw raster image file and writes the image
- X as a FORM ILBM file.
- XILBM2Raw.C
- X Example ILBM reader program. Reads a FORM ILBM file
- X and writes it into a raw raster image.
- X
- XREMALLOC.H, Remalloc.c
- X
- X Memory allocation routines used in these examples.
- X
- XINTUALL.H generic "include almost everything" include-file
- X with the sequence of includes correctly specified.
- X
- XREADPICT.H, ReadPict.c
- X
- X given an ILBM file, read it into a bitmap and
- X a color map
- X
- XPUTPICT.H, PutPict.c
- X
- X given a bitmap and a color map, save it as
- X an ILBM file.
- X
- XGIO.H, Gio.c generic I/O speedup package. Attempts to speed
- X disk I/O by buffering writes and reads.
- X
- Xgiocall.c sample call to gio.
- X
- Xilbmdump.c reads in ILBM file, prints out ascii representation
- X for including in C files.
- X
- Xbmprintc.c prints out a C-language representation of data for
- X a bitmap.
- X
- X
- X
- XExample Diagrams
- X
- XHere's a box diagram for an example IFF file, a raster image FORM
- XILBM. This FORM contains a bitmap header property chunk BMHD, a color
- Xmap property chunk CMAP, and a raster data chunk BODY. This particular
- Xraster is 320 x 200 pixels x 3 bit planes uncompressed. The "0" after
- Xthe CMAP chunk represents a zero pad byte; included since the CMAP
- Xchunk has an odd length. The text to the right of the diagram shows
- Xthe outline that would be printed by the IFFCheck utility program
- Xfor this particular file.
- X
- X +-----------------------------------+
- X |'FORM' 24070 | FORM 24070 IBLM
- X +-----------------------------------+
- X |'ILBM' |
- X +-----------------------------------+
- X | +-------------------------------+ |
- X | | 'BMHD' 20 | | .BMHD 20
- X | | 320, 200, 0, 0, 3, 0, 0, ... | |
- X | + ------------------------------+ |
- X | | 'CMAP' 21 | | .CMAP 21
- X | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | |
- X | +-------------------------------+ |
- X | 0 |
- X +-----------------------------------+
- X |'BODY' 24000 | .BODY 24000
- X |0, 0, 0, ... |
- X +-----------------------------------+
- X
- XThis second diagram shows a LIST of two FORMs ILBM sharing a common
- XBMHD property and a common CMAP property. Again, the text on the right
- Xis an outline a la IFFCheck.
- X
- X
- X +-----------------------------------------+
- X |'LIST' 48114 | LIST 48114 AAAA
- X +-----------------------------------------+
- X |'AAAA' | .PROP 62 ILBM
- X | +-----------------------------------+ |
- X | |'PROP' 62 | |
- X | +-----------------------------------+ |
- X | |'ILBM' | |
- X | +-----------------------------------+ |
- X | | +-------------------------------+ | |
- X | | | 'BMHD' 20 | | | ..BMHD 20
- X | | | 320, 200, 0, 0, 3, 0, 0, ... | | |
- X | | | ------------------------------+ | |
- X | | | 'CMAP' 21 | | | ..CMAP 21
- X | | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | | |
- X | | +-------------------------------+ | |
- X | | 0 | |
- X | +-----------------------------------+ |
- X | +-----------------------------------+ |
- X | |'FORM' 24012 | | .FORM 24012 ILBM
- X | +-----------------------------------+ |
- X | |'ILBM' | |
- X | +-----------------------------------+ |
- X | | +-----------------------------+ | |
- X | | |'BODY' 24000 | | | ..BODY 24000
- X | | |0, 0, 0, ... | | |
- X | | +-----------------------------+ | |
- X | +-----------------------------------+ |
- X | +-----------------------------------+ |
- X | |'FORM' 24012 | | .FORM 24012 ILBM
- X | +-----------------------------------+ |
- X | |'ILBM' | |
- X | +-----------------------------------+ |
- X | | +-----------------------------+ | |
- X | | |'BODY' 24000 | | | ..BODY 24000
- X | | |0, 0, 0, ... | | |
- X | | +-----------------------------+ | |
- X | +-----------------------------------+ |
- X +-----------------------------------------+
- X
- X
- X
- XAppendix B. Standards Committee
- X
- XThe following people contributed to the design of this IFF standard:
- X
- XBob "Kodiak" Burns, Commodore-Amiga
- XR. J. Mical, Commodore-Amiga
- XJerry Morrison, Electronic Arts
- XGreg Riker, Electronic Arts
- XSteve Shaw, Electronic Arts
- XBarry Walsh, Commodore-Amiga
- //END
- echo x - ftxt
- sed 's/^X//' > ftxt << '//END'
- X"FTXT" IFF Formatted Text
- X
- XDate: November 15, 1985
- XFrom: Steve Shaw and Jerry Morrison, Electronic Arts and
- X Bob "Kodiak" Burns, Commodore-Amiga
- XStatus: Draft 2.6
- X
- XDRAFT DRAFT DRAFT
- XDRAFT DRAFT DRAFT
- X
- X1. Introduction
- X
- XThis memo is the IFF supplement for FORM FTXT. An FTXT is an IFF "data
- Xsection" or "FORM type" which can be an IFF file or a part of one containing
- Xa stream of text plus optional formatting information."EA IFF 85"
- Xis Electronic Arts' standard for interchange format files. (See the
- XIFF reference.)
- X
- XAn FTXT is an archival and interchange representation designed for
- Xthree uses. The simplest use is for a "console device" or "glass teletype"
- X(the minimal 2-D text layout means): a stream of "graphic" ("printable")
- Xcharacters plus positioning characters "space" ("SP") and line terminator
- X("LF"). This is not intended for cursor movements on a screen although
- Xit does not conflict with standard cursor-moving characters. The second
- Xuse is text that has explicit formatting information (or "looks")
- Xsuch as font family and size, typeface, etc. The third use is as the
- Xlowest layer of a structured document that also has "inherited" styles
- Xto implicitly control character looks. For that use, FORMs FTXT would
- Xbe embedded within a future document FORM type. The beauty of FTXT
- Xis that these three uses are interchangeable, that is, a program written
- Xfor one purpose can read and write the others' files. So a word processor
- Xdoes not have to write a separate plain text file to communicate with
- Xother programs.
- X
- XText is stored in one or more "CHRS" chunks inside an FTXT. Each CHRS
- Xcontains a stream of 8-bit text compatible with ISO and ANSI data
- Xinterchange standards. FTXT uses just the central character set from
- Xthe ISO/ANSI standards. (These two standards are henceforth called
- X"ISO/ANSI" as in "see the ISO/ANSI reference".)
- X
- XSince it's possible to extract just the text portions from future
- Xdocument FORM types, programs can exchange data without having to
- Xsave both plain text and formatted text representations.
- X
- XCharacter looks are stored as embedded control sequences within CHRS
- Xchunks. This document specifies which class of control sequences to
- Xuse: the CSI group. This document does not yet specify their meanings,
- Xe.g. which one means "turn on italic face". Consult ISO/ANSI.
- X
- XSection 2 defines the chunk types character stream "CHRS" and font
- Xspecifier "FONS". These are the "standard" chunks. Specialized chunks
- Xfor private or future needs can be added later. Section 3 outlines
- Xan FTXT reader program that strips a document down to plain unformatted
- Xtext. Appendix A is a code table for the 8-bit ISO/ANSI character
- Xset used here. Appendix B is an example FTXT shown as a box diagram.
- XAppendix C is a racetrack diagram of the syntax of ISO/ANSI control
- Xsequences.
- X
- X
- XReference:
- X
- XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
- X
- XElectronic Arts[tm] is a trademark of Electronic Arts.
- X
- XIFF: "EA IFF 85" Standard for Interchange Format Files describes the
- Xunderlying conventions for all IFF files.
- X
- XISO/ANSI: ISO/DIS 6429.2 and ANSI X3.64-1979. International Organization
- Xfor Standardization (ISO) and American National Standards Institute
- X(ANSI) data-interchange standards. The relevant parts of these two
- Xstandards documents are identical. ISO standard 2022 is also relevant.
- X
- X
- X2. Standard Data and Property Chunks
- X
- XThe main contents of a FORM FTXT is in its character stream "CHRS"
- Xchunks. Formatting property chunks may also appear. The only formatting
- Xproperty yet defined is "FONS", a font specifier. A FORM FTXT with
- Xno CHRS represents an empty text stream. A FORM FTXT may contain nested
- XIFF FORMs, LISTs, or CATs, although a "stripping" reader (see section
- X3) will ignore them.
- X
- XCharacter Set
- X
- XFORM FTXT uses the core of the 8-bit character set defined by the
- XISO/ANSI standards cited at the start of this document. (See Appendix
- XA for a character code table.) This character set is divided into
- Xtwo "graphic" groups plus two "control" groups. Eight of the control
- Xcharacters begin ISO/ANSI standard control sequences. (See "Control
- XSequences", below.) Most control sequences and control characters
- Xare reserved for future use and for compatibility with ISO/ANSI. Current
- Xreader programs should skip them.
- X
- X% C0 is the group of control characters in the range NUL (hex
- X0) through hex 1F. Of these, only LF (hex 0A) and ESC (hex 1B) are
- Xsignificant. ESC begins a control sequence. LF is the line terminator,
- Xmeaning "go to the first horizontal position of the next line". All
- Xother C0 characters are not used. In particular, CR (hex 0D) is not
- Xrecognized as a line terminator.
- X
- X% G0 is the group of graphic characters in the range hex 20 through
- Xhex 7F. SP (hex 20) is the space character. DEL (hex 7F) is the delete
- Xcharacter which is not used. The rest are the standard ASCII printable
- Xcharacters "!" (hex 21) through "~" (hex 7E).
- X
- X% C1 is the group of extended control characters in the range
- Xhex 80 through hex 9F. Some of these begin control sequences. The
- Xcontrol sequence starting with CSI (hex 9B) is used for FTXT formatting.
- XAll other control sequences and C1 control characters are unused.
- X
- X% G1 is the group of extended graphic characters in the range
- XNBSP (hex A0) through "X" (hex FF). It is one of the alternate graphic
- Xgroups proposed for ISO/ANSI standardization.
- X
- XControl Sequences
- X
- XEight of the control characters begin ISO/ANSI standard "control sequences"
- X(or "escape sequences"). These sequences are described below and diagrammed
- Xin Appendix C.
- X
- XG0 ::= (SP through DEL)
- XG1 ::= (NBSP through "X")
- X
- XESC-Seq ::= ESC (SP through "/")* ("0" through "~")
- XShiftToG2 ::= SS2 G0
- XShiftToG3 ::= SS3 G0
- XCSI-Seq ::= CSI (SP through "?")* ("@" through "~")
- XDCS-Seq ::= (DCS | OSC | PM | APC) (SP through "~" | G1)* ST
- X
- X"ESC-Seq" is the control sequence ESC (hex 1B), followed by zero or
- Xmore characters in the range SP through "/S (hex 20 through hex 2F),
- Xfollowed by a character in the range "0" through "~" (hex 30 through
- Xhex 7E). These sequences are reserved for future use and should be
- Xskipped by current FTXT reader programs.
- X
- XSS2 (hex 8E) and SS3 (hex 8F) shift the single following G0 character
- Xinto yet-to-be-defined graphic sets G2 and G3, respectively. These
- Xsequences should not be used until the character sets G2 and G3 are
- Xstandardized. A reader may simply skip the SS2 or SS3 (taking the
- Xfollowing character as a corresponding G0 character) or replace the
- Xtwo-character sequence with a character like "?" to mean "absent".
- X
- XFTXT uses "CSI-Seq" control sequences to store character formatting
- X(font selection by number, type face, and text size) and perhaps layout
- Xinformation (position and rotation). "CSI-Seq" control sequences start
- Xwith CSI (the "control sequence introducer", hex 9B). Syntactically,
- Xthe sequence includes zero or more characters in the range SP through
- X"?" (hex 20 through hex 3F) and a concluding character in the range
- X"@" through "~" (hex 40 through hex 7E). These sequences may be skipped
- Xby a minimal FTXT reader, i.e. one that ignores formatting information.
- X
- XNote: A future FTXT standardization document will explain the uses
- Xof CSI-Seq sequences for setting character face (light weight vs.
- Xmedium vs. bold, italic vs. upright, height, pitch, position, and
- Xrotation). For now, consult the ISO/ANSI references.
- X
- X"DCS-Seq" is the control sequences starting with DCS (hex 90), OSC
- X(hex 9D), PM (hex 9E), or APC (hex 9F), followed by zero or more characters
- Xeach of which is in the range SP through "~" (hex 20 through hex 7E)
- Xor else a G1 character, and terminated by an ST (hex 9C). These sequences
- Xare reserved for future use and should be skipped by current FTXT
- Xreader programs.
- X
- XData Chunk CHRS
- X
- XA CHRS chunk contains a sequence of 8-bit characters abiding by the
- XISO/ANSI standards cited at the start of this document. This includes
- Xthe character set and control sequences as described above and summarized
- Xin Appendicies A and C.
- X
- XA FORM FTXT may contain any number of CHRS chunks. Taken together,
- Xthey represent a single stream of textual information. That is, the
- Xcontents of CHRS chunks are effectively concatenated except that (1)
- Xeach control sequence must be completely within a single CHRS chunk,
- Xand (2) any formatting property chunks appearing between two CHRS
- Xchunks affects the formatting of the latter chunk's text. Any formatting
- Xsettings set by control sequences inside a CHRS carry over to the
- Xnext CHRS in the same FORM FTXT. All formatting properties stop at
- Xthe end of the FORM since IFF specifies that adjacent FORMs are independent
- Xof each other (although not independent of any properties inherited
- Xfrom an enclosing LIST or FORM).
- X
- XProperty Chunk FONS
- X
- XThe optional property "FONS" holds a FontSpecifier as defined in the
- XC declaration below. It assignes a font to a numbered "font register"
- Xso it can be referenced by number within subsequent CHRS chunks. (This
- Xfunction is not provided within the ISO and ANSI standards.) The font
- Xspecifier gives both a name and a description for the font so the
- Xrecipient program can do font substitution.
- X
- XBy default, CHRS text uses font 1 until it selects another font. A
- Xminimal text reader always uses font 1. If font 1 hasn't been specified,
- Xthe reader may use the local system font as font 1.
- X
- X typedef struct {
- X UBYTE id;
- X /* 0 through 9 is a font id number referenced by an
- X * SGR control sequence selective parameter of 10
- X * through 19. Other values are reserved for future
- X * standardization.
- X */
- X UBYTE pad1; /* reserved for future use; store 0 here */
- X UBYTE proportional;
- X /* proportional font? 0 = unknown, 1 = no, 2 = yes */
- X UBYTE serif;
- X /* serif font? 0 = unknown, 1 = no, 2 = yes */
- X char name[];
- X /* A NULL-terminated string naming preferred font. */
- X } FontSpecifier;
- X
- XFields are filed in the order shown. The UBYTE fields are byte-packed
- X(2 per 16-bit word). The field pad1 is reserved for future standardization.
- XPrograms should store 0 there for now.
- X
- XThe field proportional indicates if the desired font is proportional
- Xwidth as opposed to fixed width. The field serif indicates if the
- Xdesired font is serif as opposed to sans serif. [Issue: Discuss font
- Xsubstitution!]
- X
- XFuture Properties
- X
- XNew optional property chunks may be defined in the future to store
- Xadditional formatting information. They will be used to represent
- Xformatting not encoded in standard ISO/ANSI control sequences and
- Xfor "inherited" formatting in structured documents. Text orientation
- Xmight be one example.
- X
- XPositioning Units
- X
- XUnless otherwise specified, position and size units used in FTXT formatting
- Xproperties and control sequences are in decipoints (720 decipoints/inch).
- XThis is ANSI/ISO Positioning Unit Mode (PUM) 2. While a metric standard
- Xmight be nice, decipoints allow the existing U.S.A. typographic units
- Xto be encoded easily, e.g. "12 points" is "120 decipoints".
- X
- X
- X3. FTXT Stripper
- X
- XAn FTXT reader program can read the text and ignore all formatting
- Xand structural information in a document FORM that uses FORMs FTXT
- Xfor the leaf nodes. This amounts to stripping a document down to a
- Xstream of plain text. It would do this by skipping over all chunks
- Xexcept FTXT.CHRS (CHRS chunks found inside a FORM FTXT) and within
- Xthe FTXT.CHRS chunks skipping all control characters and control sequences.
- X(Appendix C diagrams this text scanner.) It may also read FTXT.FONS
- Xchunks to find a description for font 1.
- X
- XHere's a Pascal-ish program for an FTXT stripper. Given a FORM (a
- Xdocument of some kind), it scans for all FTXT.CHRS chunks. This would
- Xlikely be applied to the first FORM in an IFF file.
- X
- XPROCEDURE ReadFORM4CHRS(); {Read an IFF FORM for FTXT.CHRS chunks.}
- XBEGIN
- XIF the FORM's subtype = "FTXT"
- X THEN ReadFTXT4CHRS()
- X ELSE WHILE something left to read in the FORM DO BEGIN
- X read the next chunk header;
- X CASE the chunk's ID OF
- X "LIST", "CAT ": ReadCAT4CHRS();
- X "FORM": ReadFORM4CHRS();
- X OTHERWISE skip the chunk's body;
- X END
- X END
- XEND;
- X
- X{Read a LIST or CAT for all FTXT.CHRS chunks.}
- XPROCEDURE ReadCAT4CHRS();
- X BEGIN
- XWHILE something left to read in the LIST or CAT DO BEGIN
- X read the next chunk header;
- X CASE the chunk's ID OF
- X "LIST", "CAT ": ReadCAT4CHRS();
- X "FORM": ReadFORM4CHRS();
- X "PROP": IF we're reading a LIST AND the PROP's subtype =
- X"FTXT"
- X THEN read the PROP for "FONS" chunks;
- X OTHERWISE error--malformed IFF file;
- X END
- X END
- XEND;
- X
- XPROCEDURE ReadFTXT4CHRS(); {Read a FORM FTXT for CHRS chunks.}
- XBEGIN
- XWHILE something left to read in the FORM FTXT DO BEGIN
- X read the next chunk header;
- X CASE the chunk's ID OF
- X "CHRS": ReadCHRS();
- X "FONS": BEGIN
- X read the chunk's contents into a FontSpecifier variable;
- X IF the font specifier's id = 1 THEN use this font;
- X END;
- X OTHERWISE skip the chunk's body;
- X END
- X END
- XEND;
- X
- X{Read an FTXT.CHRS. Skip all control sequences and unused control
- Xchars.}
- XPROCEDURE ReadCHRS();
- XBEGIN
- XWHILE something left to read in the CHRS chunk DO
- X CASE read the next character OF
- X LF: start a new output line;
- X ESC: SkipControl([' '..'/'], ['0'..'~']);
- X IN [' '..'~'], IN [NBSP..'X']: output the character;
- X SS2, SS3: ; {Just handle the following G0 character
- X directly, ignoring the shift to G2 or G3.}
- X CSI: SkipControl([' '..'?'], ['@'..'~']);
- X DCS, OSC, PM, APC: SkipControl([' '..'~'] + [NBSP..'X'], [ST]);
- X END
- XEND;
- X
- X{Skip a control sequence of the format (rSet)* (tSet), i.e. any number
- Xof characters in the set rSet followed by a character in the set tSet.}
- XPROCEDURE SkipControl(rSet, tSet);
- XVAR c: CHAR;
- XBEGIN
- XREPEAT c := read the next character
- X UNTIL c NOT IN rSet;
- XIF c NOT IN tSet
- X THEN put character c back into the input stream;
- XEND
- X
- XThe following program is an optimized version of the above routines
- XReadFORM4CHRS and ReadCAT4CHRS for the case where you're ignoring
- Xfonts as well as formatting. It takes advantage of certain facts of
- Xthe IFF format to read a document FORM and its nested FORMs, LISTs,
- Xand CATs without a stack. In other words, it's a hack that ignores
- Xall fonts and faces to cheaply get to the plain text of the document.
- X
- X{Cheap scan of an IFF FORM for FTXT.CHRS chunks.}
- XPROCEDURE ScanFORM4CHRS();
- XBEGIN
- XIF the document FORM's subtype = "FTXT"
- X THEN ReadFTXT4CHRS()
- X ELSE WHILE something left to read in the FORM DO BEGIN
- X read the next chunk header;
- X IF it's a group chunk (LIST, FORM, PROP, or CAT)
- X THEN read its subtype ID;
- X CASE the chunk's ID OF
- X "LIST", "CAT ":; {NOTE: See explanation below.*}
- X "FORM": IF this FORM's subtype = "FTXT" THEN
- X ReadFTXT4CHRS()
- X ELSE; {NOTE: See explanation below.*}
- X OTHERWISE skip the chunk's body;
- X END
- X END
- XEND;
- X
- X*Note: This implementation is subtle. After reading a group header
- Xother than FORM FTXT it just continues reading. This amounts to reading
- Xall the chunks inside that group as if they weren't nested in a group.
- X
- X
- XAppendix A: Character Code Table
- X
- XThis table corresponds to the ISO/DIS 6429.2 and ANSI X3.64-1979 8-bit
- Xcharacter set standards. Only the core character set of those standards
- Xis used in FTXT.
- X
- XTwo G1 characters aren't defined in the standards and are shown as
- Xdark gray entries in this table. Light gray shading denotes control
- Xcharacters. (DEL is a control character although it belongs to the
- Xgraphic group G0.) The following five rare G1 characters are left
- Xblank in the table below due to limitations of available fonts: hex
- XA8, D0, DE, F0, and FE.
- X
- X
- X
- X ISO/DIS 6429.2 and ANSI X3.64-1979 Character Code Table
- X
- X
- X (figure named "TextTable", viewable by ShowILBM or SeeILBM)
- X
- X
- X[_____] [_______________________] [_____] [____________________________]
- XControl Grapic Group Control Graphic Group
- X Group G0 Group G1
- X C0 C1
- X
- X"NBSP" is a "non-breaking space"
- X"SHY" is a "soft-hyphen"
- X
- X
- X
- XAppendix B. FTXT Example
- X
- XHere's a box diagram for a simple example: "The quick brown fox jumped.Four
- Xscore and seven", written in a proportional serif font named "Roman".
- X
- X
- X +-----------------------------------+
- X |'FORM' 24070 | FORM 24070 ILBM
- X +-----------------------------------+
- X |'ILBM' |
- X +-----------------------------------+
- X | +-------------------------------+ |
- X | | 'BMHD' 20 | | .BMHD 20
- X | | 320, 200, 0, 0, 3, 0, 0, ... | |
- X | | ------------------------------+ |
- X | | 'CMAP' 21 | | .CMAP 21
- X | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | |
- X | +-------------------------------+ |
- X | +-------------------------------+ |
- X | |'BODY' 24000 | | .BODY 24000
- X | |0, 0, 0, ... | |
- X | +-------------------------------+ |
- X +-----------------------------------+
- X
- XThe "0" after the CMAP chunk is a pad byte.
- X
- X
- X
- X
- XAppendix B. Standards Committee
- X
- XThe following people contributed to the design of this IFF standard:
- X
- XBob "Kodiak" Burns, Commodore-Amiga
- XR. J. Mical, Commodore-Amiga
- XJerry Morrison, Electronic Arts
- XGreg Riker, Electronic Arts
- XSteve Shaw, Electronic Arts
- XBarry Walsh, Commodore-Amiga
- X
- X
- X
- XAppendix C. ISO/ANSI Control Sequences
- X
- XThis is a racetrack diagram of the ISO/ANSI characters and control
- Xsequences as used in FTXT CHRS chunks.
- X
- X line terminator
- X-----+-------------------> LF --------------------------------------->
- X | ESC-Seq
- X +-------------------> ESC ---+>----------------+--> 0 thru ~ --->
- X | | |
- X | +-- SP thru / <---+
- X | printable
- X +---------------+---> SP thru ~ --+->--------------------------->
- X | | |
- X | +---> G1 -------->+
- X | shift to G2
- X +-------------------> SS2 ----> G0 ---> (produces a G2 character)
- X | shift to G3
- X +-------------------> SS3 ----> G0 ---> (produces a G3 character)
- X | CSI-Seq
- X +-------------------> CSI ---+>----------------+--> @ thru ~ --->
- X | | |
- X | +-- SP thru ? <---+
- X | DCS-Seq
- X +----------> DCS,OSC,PM,or APC --+>-------------+--+-> ST -+---->
- X | | | | |
- X | +- SP thru ~ <-+ +-> G1 -+
- X | discard
- X +----------> any other character ------------------------------->
- X
- X
- X
- XOf the various control sequences, only CSI-Seq is used for FTXT character
- Xformatting information. The others are reserved for future use and
- Xfor compatibility with ISO/ANSI standards. Certain character sequences
- Xare syntactically malformed, e.g. CSI followed by a C0, C1, or G1
- Xcharacter. Writer programs should not generate reserved or malformed
- Xsequences and reader programs should skip them.
- X
- XConsult the ISO/ANSI standards for the meaning of the CSI-Seq control
- Xsequences.
- X
- XThe two character set shifts SS2 and SS3 may be used when the graphic
- Xcharacter groups G2 and G3 become standardized.
- X
- //END
- echo x - ilbm
- sed 's/^X//' > ilbm << '//END'
- X"ILBM" IFF Interleaved Bitmap
- X
- XDate: January 17, 1986
- XFrom: Jerry Morrison, Electronic Arts
- XStatus: Released and in use
- X
- X1. Introduction
- X
- X"EA IFF 85" is Electronic Arts' standard for interchange format files.
- X"ILBM" is a format for a 2 dimensional raster graphics image, specifically
- Xan InterLeaved bitplane BitMap image with color map. An ILBM is an
- XIFF "data section" or "FORM type", which can be an IFF file or a part
- Xof one. (See the IFF reference.)
- X
- XAn ILBM is an archival representation designed for three uses. First,
- Xa standalone image that specifies exactly how to display itself (resolution,
- Xsize, color map, etc.). Second, an image intended to be merged into
- Xa bigger picture which has its own depth, color map, and so on. And
- Xthird, an empty image with a color map selection or "palette" for
- Xa paint program. ILBM is also intended as a building block for composite
- XIFF FORMs like "animation sequence" and "structured graphics". Some
- Xuses of ILBM will be to preserve as much information as possible across
- Xdisparate environments. Other uses will be to store data for a single
- Xprogram or highly cooperative programs while maintaining subtle details.
- XSo we're trying to accomplish a lot with this one format.
- X
- XThis memo is the IFF supplement for FORM ILBM. Section 2 defines the
- Xpurpose and format of property chunks bitmap header "BMHD", color
- Xmap "CMAP", hotspot "GRAB", destination merge data "DEST", sprite
- Xinformation "SPRT", and Commodore Amiga viewport mode "CAMG". Section
- X3 defines the standard data chunk "BODY". These are the "standard"
- Xchunks. Section 4 defines the nonstandard color range data chunk "CRNG".
- XAdditional specialized chunks like texture pattern can be added later.
- XThe ILBM syntax is summarized in Appendix A as a regular expression
- Xand in Appendix B as a box diagram. Appendix C explains the optional
- Xrun encoding scheme. Appendix D names the committee responsible for
- Xthis FORM ILBM standard.
- X
- XDetails of the raster layout are given in part 3, "Standard Data Chunk".
- XSome elements are based on the Commodore Amiga hardware but generalized
- Xfor use on other computers. An alternative to ILBM would be appropriate
- Xfor computers with true color data in each pixel.
- X
- XReference:
- X
- X"EA IFF 85" Standard for Interchange Format Files describes the underlying
- Xconventions for all IFF files.
- X
- XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
- XElectronic Arts[tm] is a trademark of Electronic Arts.
- XMacintosh[tm] is a trademark licensed to Apple Computer, Inc.
- XMacPaint[tm] is a trademark of Apple Computer, Inc.
- X
- X
- X2. Standard Properties
- X
- XThe required property "BMHD" and any optional properties must appear
- Xbefore any "BODY" chunk. (Since an ILBM has only one BODY chunk, any
- Xfollowing properties are superfluous.) Any of these properties may
- Xbe shared over a LIST of FORMs IBLM by putting them in a PROP ILBM.
- X(See the "EA IFF 85" memo.)
- X
- XBMHD
- X
- XThe required property "BMHD" holds a BitMapHeader as defined in these
- XC declarations and following documentation. It describes the dimensions
- Xand encoding of the image, including data necessary to understand
- Xthe BODY chunk to follow.
- X
- Xtypedef UBYTE Masking; /* Choice of masking technique. */
- X
- X#define mskNone 0
- X#define mskHasMask 1
- X#define mskHasTransparentColor 2
- X#define mskLasso 3
- X
- Xtypedef UBYTE Compression;
- X /* Choice of compression algorithm applied to the rows of all
- X * source and mask planes. "cmpByteRun1" is the byte run encoding
- X * described in Appendix C. Do not compress across rows! */
- X#define cmpNone 0
- X#define cmpByteRun1 1
- X
- Xtypedef struct {
- X UWORD w, h; /* raster width & height in pixels */
- X WORD x, y; /* pixel position for this image */
- X UBYTE nPlanes; /* # source bitplanes */
- X Masking masking;
- X Compression compression;
- X UBYTE pad1; /* unused; for consistency, put 0 here */
- X UWORD transparentColor; /* transparent "color number" (sort of) */
- X UBYTE xAspect, yAspect; /* pixel aspect, a ratio width : height */
- X WORD pageWidth, pageHeight; /* source "page" size in pixels */
- X } BitMapHeader;
- X
- XFields are filed in the order shown. The UBYTE fields are byte-packed.
- X
- XThe fields w and h indicate the size of the image rectangle in pixels.
- XEach row of the image is stored in an integral number of 16 bit words.
- XThe number of words per row is Ceiling(w/16). The fields x and y indicate
- Xthe desired position of this image within the destination picture.
- XSome reader programs may ignore x and y. A safe default for writing
- Xan ILBM is (x, y) = (0, 0).
- X
- XThe number of source bitplanes in the BODY chunk (see below) is stored
- Xin nPlanes. An ILBM with a CMAP but no BODY and nPlanes = 0 is the
- Xrecommended way to store a color map.
- X
- XNote: Color numbers are color map index values formed by pixels in
- Xthe destination bitmap, which may be deeper than nPlanes if a DEST
- Xchunk calls for merging the image into a deeper image.
- X
- XThe field masking indicates what kind of masking is to be used for
- Xthis image. The value mskNone designates an opaque rectangular image.
- XThe value mskHasMask means that a mask plane is interleaved with the
- Xbitplanes in the BODY chunk (see below). The value mskHasTransparentColor
- Xindicates that pixels in the source planes matching transparentColor
- Xare to be considered "transparent". (Actually, transparentColor isn't
- Xa "color number" since it's matched with numbers formed by the source
- Xbitmap rather than the possibly deeper destination bitmap. Note that
- Xhaving a transparent color implies ignoring one of the color registers.
- XSee CMAP, below.) The value mskLasso indicates the reader may construct
- Xa mask by lassoing the image as in MacPaint*. To do this, put a 1
- Xpixel border of transparentColor around the image rectangle. Then
- Xdo a seed fill from this border. Filled pixels are to be transparent.
- X
- XIssue: Include in an appendix an algorithm for converting a transparent
- Xcolor to a mask plane, and maybe a lasso algorithm.
- X
- XA code indicating the kind of data compression used is stored in compression.
- XBeware that using data compression makes your data unreadable by programs
- Xthat don't implement the matching decompression algorithm. So we'll
- Xemploy as few compression encodings as possible. The run encoding
- XbyteRun1 is documented in Appendix C, below.
- X
- XThe field pad1 is a pad byte and must be set to 0 for consistency.
- XThis field could get used in the future.
- X
- XThe transparentColor specifies which bit pattern means "transparent".
- XThis only applies if masking is mskHasTransparentColor or mskLasso
- X(see above). Otherwise, transparentColor should be 0.
- X
- XThe pixel aspect ratio is stored as a ratio in the two fields xAspect
- Xand yAspect. This may be used by programs to compensate for different
- Xaspects or to help interpret the fields w, h, x, y, pageWidth, and
- XpageHeight, which are in units of pixels. The fraction xAspect/yAspect
- Xrepresents a pixel's width/height. It's recommended that your programs
- Xstore proper fractions in BitMapHeaders, but aspect ratios can always
- Xbe correctly compared with the the test
- X
- XxAspect%yDesiredAspect = yAspect%xDesiredAspect
- X
- XTypical values for aspect ratio are width : height = 10 : 11 (Amiga
- X320 x 200 display) and 1 : 1 (Macintosh*).
- X
- XThe size in pixels of the source "page" (any raster device) is stored
- Xin pageWidth and pageHeight, e.g. (320, 200) for a low resolution
- XAmiga display. This information might be used to scale an image or
- Xto automatically set the display format to suit the image. (The image
- Xcan be larger than the page.)
- X
- XCMAP
- X
- XThe optional (but encouraged) property "CMAP" stores color map data
- Xas triplets of red, green, and blue intensity values. The n color
- Xmap entries ("color registers") are stored in the order 0 through
- Xn-1, totaling 3n bytes. Thus n is the ckSize/3. Normally, n would
- Xequal 2nPlanes.
- X
- XA CMAP chunk contains a ColorMap array as defined below. (These typedefs
- Xassume a C compiler that implements packed arrays of 3-byte elements.)
- X
- Xtypedef struct {
- X UBYTE red, green, blue; /* color intensities 0..255 */
- X } ColorRegister; /* size = 3 bytes */
- X
- Xtypedef ColorRegister ColorMap[n]; /* size = 3n bytes */
- X
- XThe color components red, green, and blue represent fractional intensity
- Xvalues in the range 0 through 255 256ths. White is (255, 255, 255)
- Xand black is (0, 0, 0). If your machine has less color resolution,
- Xuse the high order bits. Shift each field right on reading (or left
- Xon writing) and assign it to (from) a field in a local packed format
- Xlike Color4, below. This achieves automatic conversion of images across
- Xenvironments with different color resolutions. On reading an ILBM,
- Xuse defaults if the color map is absent or has fewer color registers
- Xthan you need. Ignore any extra color registers.
- X
- XThe example type Color4 represents the format of a color register
- Xin working memory of an Amiga computer, which has 4 bit video DACs.
- X(The ":4" tells the C compiler to pack the field into 4 bits.)
- X
- Xtypedef struct {
- X unsigned pad1 :4, red :4, green :4, blue :4;
- X } Color4; /* Amiga RAM format. Not filed. */
- X
- XRemember that every chunk must be padded to an even length, so a color
- Xmap with an odd number of entries would be followed by a 0 byte, not
- Xincluded in the ckSize.
- X
- XGRAB
- X
- XThe optional property "GRAB" locates a "handle" or "hotspot" of the
- Ximage relative to its upper left corner, e.g. when used as a mouse
- Xcursor or a "paint brush". A GRAB chunk contains a Point2D.
- X
- Xtypedef struct {
- X WORD x, y; /* relative coordinates (pixels) */
- X } Point2D;
- X
- XDEST
- X
- XThe optional property "DEST" is a way to say how to scatter zero or
- Xmore source bitplanes into a deeper destination image. Some readers
- Xmay ignore DEST.
- X
- XThe contents of a DEST chunk is DestMerge structure:
- X
- Xtypedef struct {
- X UBYTE depth; /* # bitplanes in the original source */
- X UBYTE pad1; /* unused; for consistency put 0 here */
- X UWORD planePick; /* how to scatter source bitplanes into destination */
- X UWORD planeOnOff; /* default bitplane data for planePick */
- X UWORD planeMask; /* selects which bitplanes to store into */
- X } DestMerge;
- X
- XThe low order depth number of bits in planePick, planeOnOff, and planeMask
- Xcorrespond one-to-one with destination bitplanes. Bit 0 with bitplane
- X0, etc. (Any higher order bits should be ignored.) "1" bits in planePick
- Xmean "put the next source bitplane into this bitplane", so the number
- Xof "1" bits should equal nPlanes. "0" bits mean "put the corresponding
- Xbit from planeOnOff into this bitplane". Bits in planeMask gate writing
- Xto the destination bitplane: "1" bits mean "write to this bitplane"
- Xwhile "0" bits mean "leave this bitplane alone". The normal case (with
- Xno DEST property) is equivalent to planePick = planeMask = 2nPlanesJ-
- X1.
- X
- XRemember that color numbers are formed by pixels in the destination
- Xbitmap (depth planes deep) not in the source bitmap (nPlanes planes
- Xdeep).
- X
- XSPRT
- X
- XThe presence of an "SPRT" chunk indicates that this image is intended
- Xas a sprite. It's up to the reader program to actually make it a sprite,
- Xif even possible, and to use or overrule the sprite precedence data
- Xinside the SPRT chunk:
- X
- Xtypedef UWORD SpritePrecedence; /* relative precedence, 0 is the highest */
- X
- XPrecedence 0 is the highest, denoting a sprite that is foremost.
- X
- XCreating a sprite may imply other setup. E.g. a 2 plane Amiga sprite
- Xwould have transparentColor = 0. Color registers 1, 2, and 3 in the
- XCMAP would be stored into the correct hardware color registers for
- Xthe hardware sprite number used, while CMAP color register 0 would
- Xbe ignored.
- X
- XCAMG
- X
- XA "CAMG" chunk is specifically for the Commodore Amiga computer. It
- Xstores a LONG "viewport mode". This lets you specify Amiga display
- Xmodes like "dual playfield" and "hold and modify".
- X3. Standard Data Chunk
- X
- XRaster Layout
- X
- XRaster scan proceeds left-to-right (increasing X) across scan lines,
- Xthen top-to-bottom (increasing Y) down columns of scan lines. The
- Xcoordinate system is in units of pixels, where (0,0) is the upper
- Xleft corner.
- X
- XThe raster is typically organized as bitplanes in memory. The corresponding
- Xbits from each plane, taken together, make up an index into the color
- Xmap which gives a color value for that pixel. The first bitplane,
- Xplane 0, is the low order bit of these color indexes.
- X
- XA scan line is made of one "row" from each bitplane. A row is one
- XplanesU bits for one scan line, but padded out to a word (2 byte)
- Xboundary (not necessarily the first word boundary). Within each row,
- Xsuccessive bytes are displayed in order and the most significant bit
- Xof each byte is displayed first.
- X
- XA "mask" is an optional "plane" of data the same size (w, h) as a
- Xbitplane. It tells how to "cut out" part of the image when painting
- Xit onto another image."One" bits in the mask mean "copy the corresponding
- Xpixel to the destination" while "zero" mask bits mean "leave this
- Xdestination pixel alone". In other words, "zero" bits designate transparent
- Xpixels.
- X
- XThe rows of the different bitplanes and mask are interleaved in the
- Xfile (see below). This localizes all the information pertinent to
- Xeach scan line. It makes it much easier to transform the data while
- Xreading it to adjust the image size or depth. It also makes it possible
- Xto scroll a big image by swapping rows directly from the file without
- Xrandom-accessing to all the bitplanes.
- X
- XBODY
- X
- XThe source raster is stored in a "BODY" chunk. This one chunk holds
- Xall bitplanes and the optional mask, interleaved by row.
- X
- XThe BitMapHeader, in a BMHD property chunk, specifies the raster's
- Xdimensions w, h, and nPlanes. It also holds the masking field which
- Xindicates if there is a mask plane and the compression field which
- Xindicates the compression algorithm used. This information is needed
- Xto interpret the BODY chunk, so the BMHD chunk must appear first.
- XWhile reading an ILBM's BODY, a program may convert the image to another
- Xsize by filling (with transparentColor) or clipping.
- X
- XThe BODY's content is a concatenation of scan lines. Each scan line
- Xis a concatenation of one row of data from each plane in order 0 through
- XnPlanes-1 followed by one row from the mask (if masking = hasMask
- X). If the BitMapHeader field compression is cmpNone, all h rows are
- Xexactly Ceiling(w/16) words wide. Otherwise, every row is compressed
- Xaccording to the specified algorithm and their stored widths depend
- Xon the data compression.
- X
- XReader programs that require fewer bitplanes than appear in a particular
- XILBM file can combine planes or drop the high-order (later) planes.
- XSimilarly, they may add bitplanes and/or discard the mask plane.
- X
- XDo not compress across rows and don't forget to compress the mask
- Xjust like the bitplanes. Remember to pad any BODY chunk that contains
- Xan odd number of bytes.
- X4. Nonstandard Data Chunk
- X
- XThe following data chunk was defined after various programs began
- Xusing FORM ILBM so it's a "nonstandard" chunk. That means there's
- Xsome slight chance of name collisions.
- X
- XCRNG
- X
- XA "CRNG" chunk contains "color register range" information. It's used
- Xby Electronic Arts' Deluxe Paint program to identify a contiguous
- Xrange of color registers for a "shade range" and color cycling. There
- Xcan be zero or more CRNG chunks in an ILBM, but all should appear
- Xbefore the BODY chunk. Deluxe Paint normally writes 4 CRNG chunks
- Xin an ILBM when the user asks it to "Save Picture".
- X
- Xtypedef struct {
- X WORD pad1; /* reserved for future use; store 0 here */
- X WORD rate; /* color cycle rate */
- X WORD active; /* nonzero means cycle the colors */
- X UBYTE low, high; /* lower and upper color registers selected */
- X } CRange;
- X
- XThe fields low and high indicate the range of color registers (color
- Xnumbers) selected by this CRange.
- X
- XThe field active indicates whether color cycling is on or off. Zero
- Xmeans off.
- X
- XThe field rate determines the speed at which the colors will step
- Xwhen color cycling is on. The units are such that a rate of 60 steps
- Xper second is represented as 214 = 16384. Slower rates can be obtained
- Xby linear scaling: for 30 steps/second, rate = 8192; for 1 step/second,
- Xrate = 16384/60 E 273.
- X
- XCCRT
- X
- XCommodore's Graphicraft program uses a similar chunk "CCRT" (for Color
- XCyling Range and Timing). This chunk contains a CycleInfo structure.
- X
- Xtypedef struct {
- X WORD direction; /* 0 = don't cycle. 1 = cycle forwards (1, 2, 3).
- X * -1 = cycle backwards (3, 2, 1) */
- X UBYTE start, end; /* lower and upper color registers selected */
- X LONG seconds; /* # seconds between changing colors */
- X LONG microseconds; /* # microseconds between changing colors */
- X WORD pad; /* reserved for future use; store 0 here */
- X } CycleInfo;
- X
- XThis is pretty similar to a CRNG chunk. A program would probably only
- Xuse one of these two methods of expressing color cycle data. You could
- Xwrite out both if you want to communicate this information to both
- XDeluxe Paint and Graphicraft.
- X
- XA CCRT chunk expresses the color cycling rate as a number of seconds
- Xplus a number of microseconds.
- X
- X
- X
- XAppendix A. ILBM Regular Expression
- X
- XHere's a regular expression summary of the FORM ILBM syntax. This
- Xcould be an IFF file or a part of one.
- X
- XILBM ::= "FORM" #{ "ILBM" BMHD [CMAP] [GRAB] [DEST] [SPRT] [CAMG]
- X CRNG* CCRT* [BODY] }
- X
- XBMHD ::= "BMHD" #{ BitMapHeader }
- XCMAP ::= "CMAP" #{ (red green blue)* } [0]
- XGRAB ::= "GRAB" #{ Point2D }
- XDEST ::= "DEST" #{ DestMerge }
- XSPRT ::= "SPRT" #{ SpritePrecendence }
- XCAMG ::= "CAMG" #{ LONG }
- X
- XCRNG ::= "CRNG" #{ CRange }
- XCCRT ::= "CCRT" #{ CycleInfo }
- XBODY ::= "BODY" #{ UBYTE* } [0]
- X
- XThe token "#" represents a ckSize LONG count of the following {braced}
- Xdata bytes. E.g. a BMHD's "#" should equal sizeof(BitMapHeader). Literal
- Xstrings are shown in "quotes", [square bracket items] are optional,
- Xand "*" means 0 or more repetitions. A sometimes-needed pad byte is
- Xshown as "[0]".
- X
- XThe property chunks (BMHD, CMAP, GRAB, DEST, SPRT, and CAMG) and any
- XCRNG and CCRT data chunks may actually be in any order but all must
- Xappear before the BODY chunk since ILBM readers usually stop as soon
- Xas they read the BODY. If any of the 6 property chunks are missing,
- Xdefault values are "inherited" from any shared properties (if the
- XILBM appears inside an IFF LIST with PROPs) or from the reader program's
- Xdefaults. If any property appears more than once, the last occurrence
- Xbefore the BODY is the one that counts since that's the one that modifies
- Xthe BODY.
- X
- X
- X
- XAppendix B. ILBM Box Diagram
- X
- XHere's a box diagram for a simple example: an uncompressed image 320
- Xx 200 pixels x 3 bitplanes. The text to the right of the diagram shows
- Xthe outline that would be printed by the IFFCheck utility program
- Xfor this particular file.
- X
- X
- X +-----------------------------------+
- X |'FORM' 24070 | FORM 24070 IBLM
- X +-----------------------------------+
- X |'ILBM' |
- X +-----------------------------------+
- X | +-------------------------------+ |
- X | | 'BMHD' 20 | | .BMHD 20
- X | | 320, 200, 0, 0, 3, 0, 0, ... | |
- X | + ------------------------------+ |
- X | | 'CMAP' 21 | | .CMAP 21
- X | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | |
- X | +-------------------------------+ |
- X | 0 |
- X +-----------------------------------+
- X |'BODY' 24000 | .BODY 24000
- X |0, 0, 0, ... |
- X +-----------------------------------+
- X
- X
- X
- XThe "0" after the CMAP chunk is a pad byte.
- X
- X
- X
- XAppendix C. ByteRun1 Run Encoding
- X
- XThe run encoding scheme byteRun1 is best described by psuedo code
- Xfor the decoder Unpacker (called UnPackBits in the Macintosh* toolbox):
- X
- XUnPacker:
- X LOOP until produced the desired number of bytes
- X Read the next source byte into n
- X SELECT n FROM
- X [0..127] => copy the next n+1 bytes literally
- X [-1..-127] => replicate the next byte -n+1 times
- X -128 => noop
- X ENDCASE;
- X ENDLOOP;
- X
- XIn the inverse routine Packer, it's best to encode a 2 byte repeat
- Xrun as a replicate run except when preceded and followed by a literal
- Xrun, in which case it's best to merge the three into one literal run.
- XAlways encode 3 byte repeats as replicate runs.
- X
- XRemember that each row of each scan line of a raster is separately
- Xpacked.
- X
- X
- X
- XAppendix D. Standards Committee
- X
- XThe following people contributed to the design of this FORM ILBM standard:
- X
- XBob "Kodiak" Burns, Commodore-Amiga
- XR. J. Mical, Commodore-Amiga
- XJerry Morrison, Electronic Arts
- XGreg Riker, Electronic Arts
- XSteve Shaw, Electronic Arts
- XDan Silva, Electronic Arts
- XBarry Walsh, Commodore-Amiga
- //END
- echo x - smus
- sed 's/^X//' > smus << '//END'
- X"SMUS" IFF Simple Musical Score
- X
- XDate: February 5, 1986
- XFrom: Jerry Morrison, Electronic Arts
- XStatus: Adopted
- X
- X1. Introduction
- X
- XThis is a reference manual for the data interchange format "SMUS",
- Xwhich stands for Simple MUsical Score. "EA IFF 85" is Electronic Arts'
- Xstandard for interchange format files. A FORM (or "data section")
- Xsuch as FORM SMUS can be an IFF file or a part of one. [See "EA IFF
- X85" Electronic Arts Interchange File Format.]
- X
- XSMUS is a practical data format for uses like moving limited scores
- Xbetween programs and storing theme songs for game programs. The format
- Xshould be geared for easy read-in and playback. So FORM SMUS uses
- Xthe compact time encoding of Common Music Notation (half notes, dotted
- Xquarter rests, etc.). The SMUS format should also be structurally
- Xsimple. So it has no provisions for fancy notational information needed
- Xby graphical score editors or the more general timing (overlapping
- Xnotes, etc.) and continuous data (pitch bends, etc.) needed by
- Xperformance-oriented MIDI recorders and sequencers.
- X
- XA SMUS score can say which "instruments" are supposed play which notes.
- XBut the score is independent of whatever output device and driver
- Xsoftware is used to perform the notes. The score can contain device-
- Xand driver-dependent instrument data, but this is just a cache. As
- Xlong as a SMUS file stays in one environment, the embedded instrument
- Xdata is very convenient. When you move a SMUS file between programs
- Xor hardware configurations, the contents of this cache usually become
- Xuseless.
- X
- XLike all IFF formats, SMUS is a filed or "archive" format. It is completely
- Xindependent of score representations in working memory, editing operations,
- Xuser interface, display graphics, computation hardware, and sound
- Xhardware. Like all IFF formats, SMUS is extensible.
- X
- XSMUS is not an end-all musical score format. Other formats may be
- Xmore appropriate for certain uses. (We'd like to design an general-use
- XIFF score format "GSCR". FORM GSCR would encode fancy notational data
- Xand performance data. There would be a SMUS to/from GSCR converter.)
- X
- XSection 2 gives important background information. Section 3 details
- Xthe SMUS components by defining the required property score header
- X"SHDR", the optional text properties name "NAME", copyright "(c) ",
- Xand author "AUTH", optional text annotation "ANNO", the optional instrument
- Xspecifier "INS1", and the track data chunk "TRAK". Section 4 defines
- Xsome chunks for particular programs to store private information.
- XThese are "standard" chunks; specialized chunks for future needs can
- Xbe added later. Appendix A is a quick-reference summary. Appendix
- XB is an example box diagram. Appendix C names the committee responsible
- Xfor this standard.
- X
- XUpdate: This standard has been revised since the draft versions. The
- X"INST" chunk type was revised to form the "INS1" chunk type. Also,
- Xseveral SEvent types and a few text chunk types have been added.
- X
- XNote: This is a MacWrite[tm] 4.5 document. If you strip it down to a
- Xtext file, you'll lose pictures, significant formatting information
- Xlike superscripts, and characters like ")". Don't do it.
- X
- X
- X ----------------------------------------------------------------
- X |(Sorry, EA. We had to strip it down for ease of distribution, |
- X | but we did convert pictures to text-form and where we could |
- X | not do that, we provided ILBM illustrations that people |
- X | could actually show using the standard "showilbm" program) |
- X ----------------------------------------------------------------
- X
- X
- XReferences:
- X
- X"EA IFF 85" Standard for Interchange Format Files describes the underlying
- Xconventions for all IFF files.
- X
- X"8SVX" IFF 8-Bit Sampled Voice documents a data format for sampled
- Xinstruments.
- X
- XElectronic Arts[tm] is a trademark of Electronic Arts.
- X
- XMIDI: Musical Instrument Digital Interface Specification 1.0, International
- XMIDI Association, 1983.
- X
- XMacWrite[tm] is a trademark of Apple Computer, Inc.
- X
- XSSSP: See various articles on Structured Sound Synthesis Project in
- XFoundations of Computer Music.
- X
- X
- X
- X
- X2. Background
- X
- XHere's some background information on score representation in general
- Xand design choices for SMUS.
- X
- XFirst, we'll borrow some terminology from the Structured Sound Synthesis
- XProject. [See the SSSP reference.] A "musical note" is one kind of
- Xscheduled event. It's properties include an event duration, an event
- Xdelay, and a timbre object. Theevent duration tells the scheduler
- Xhow long the note should last. The event delay tells how long after
- Xstarting this note to wait before starting the next event. The timbre
- Xobject selects sound driver data for the note; an "instrument" or
- X"timbre". A "rest" is a sort of a null event. Its only property is
- Xan event delay.
- X
- XClassical Event Durations
- X
- XSMUS is geared for "classical" scores, not free-form performances.
- XSo its event durations are classical (whole note, dotted quarter rest,
- Xetc.). It can tie notes together to build a "note event" with an unusual
- Xevent duration.
- X
- XThe set of useful classical durations is very small. So SMUS needs
- Xonly a handful of bits to encode an event duration. This is very compact.
- XIt's also very easy to display in Common Music Notation (CMN).
- X
- XTracks
- X
- XThe events in a SMUS score are grouped into parallel "tracks". Each
- Xtrack is a linear stream of events.
- X
- XWhy use tracks? Tracks serve 4 functions:
- X
- X1. Tracks make it possible to encode event delays very compactly.
- XA "classical" score has chorded notes and sequential notes; no overlapping
- Xnotes. That is, each event begins either simultaneous with or immediately
- Xfollowing the previous event in that track. So each event delay is
- Xeither 0 or the same as the event's duration. This binary distinction
- Xrequires only one bit of storage.
- X
- X2. Tracks represent the "voice tracks" in Common Music Notation.
- XCMN organizes a score in parallel staves, with one or two "voice tracks"
- Xper staff. So one or two SMUS tracks represents a CMN staff.
- X
- X3. Tracks are a good match to available sound hardware. We can
- Xuse "instrument settings" in a track to store the timbre assignments
- Xfor that track's notes. The instrument setting may change over the
- Xtrack.
- X
- X Furthermore, tracks can help to allocate notes among available
- Xoutput channels or performance devices or tape recorder "tracks".
- XTracks can also help to adapt polyphonic data to monophonic output
- Xchannels.
- X
- X4. Tracks are a good match to simple sound software. Each track
- Xis a place to hold state settings like "dynamic mark pp ", "time signature
- X3/4", "mute this track", etc., just as it's a context for instrument
- Xsettings. This is a lot like a text stream with running "font" and
- X"face" properties (attributes). Running state is usually more compact
- Xthan, say, storing an instrument setting in every note event. It's
- Xalso a useful way to organize "attributes" of notes. With "running
- Xtrack state" we can define new note attributes in an upward- and
- Xbackward-compatible way.
- X
- X Running track state can be expanded (run decoded) while loading
- Xa track into memory or while playing the track. The runtime track
- Xstate must be reinitialized every time the score is played.
- X
- XSeparated vs. interleaved tracks. Multi-track data could be stored
- Xeither as separate event streams or interleaved into one stream. To
- Xinterleave the streams, each event has to carry a "track number" attribute.
- X
- XIf we were designing an editable score format, we might interleave
- Xthe streams so that nearby events are stored nearby. This helps when
- Xsearching the data, especially if you can't fit the entire score into
- Xmemory at once. But it takes extra storage for the track numbers and
- Xmay take extra work to manipulate the interleaved tracks.
- X
- XThe musical score format FORM SMUS is intended for simple loading
- Xand playback of small scores that fit entirely in main memory. So
- Xwe chose to store its tracks separately.
- X
- XThere can be up to 255 tracks in a FORM SMUS. Each track is stored
- Xas a TRAK chunk. The count of tracks (the number of TRAK chunks) is
- Xrecorded in the SHDR chunk at the beginning of the FORM SMUS. The
- XTRAK chunks appear in numerical order 1, 2, 3, .... This is also priority
- Xorder, most important track first. A player program that can handle
- Xup to N parallel tracks should read the first N tracks and ignore
- Xany others.
- X
- XThe different tracks in a score may have different lengths. This is
- Xtrue both of storage length and of playback duration.
- X
- XInstrument Registers
- X
- XInstrument reference. In SSSP, each note event points to a "timbre
- Xobject" which supplies the "instrument" (the sound driver data) for
- Xthat note. FORM SMUS stores these pointers as a "current instrument
- Xsetting" for each track. It's just a run encoded version of the same
- Xinformation. SSSP uses a symbol table to hold all the pointers to
- X"timbre object". SMUS uses INS1 chunks for the same purpose. They
- Xname the score's instruments.
- X
- XThe actual instrument data to use depends on the playback environment,
- Xbut we want the score to be independent of environment. Different
- Xplayback environments have different audio output hardware and different
- Xsound driver software. And there are channel allocation issues like
- Xhow many output channels there are, which ones are polyphonic, and
- Xwhich I/O ports they're connected to. If you use MIDI to control the
- Xinstruments, you get into issues of what kind of device is listening
- Xto each MIDI channel and what each of its preset sounds like. If you
- Xuse computer-based instruments, you need driver-specific data like
- Xwaveform tables and oscillator parameters.
- X
- XWe just want to put some orchestration in the score. If the score
- Xwants a "piano", we let the playback program to find a "piano".
- X
- XInstrument reference by name. A reference from a SMUS score to actual
- Xinstrument data is normally by name. The score simply names the instrument,
- Xfor instance "tubular bells". It's up to the player program to find
- Xsuitable instrument data for its output devices. (More on locating
- Xinstruments below.)
- X
- XInstrument reference by MIDI channel and preset. A SMUS score can
- Xalso ask for a specific MIDI channel number and preset number. MIDI
- Xprograms may honor these specific requests. But these channel allocations
- Xcan become obsolete or the score may be played without MIDI hardware.
- XIn such cases, the player program should fall back to instrument reference
- Xby name.
- X
- XInstrument reference via instrument register. Each reference from
- Xa SMUS track to an instrument is via an "instrument register". Each
- Xtrack selects an instrument register which in turn points to the specific
- Xinstrument data.
- X
- XEach score has an array of instrument registers. Each track has a
- X"current instrument setting", which is simply an index number into
- Xthis array. This is like setting a raster image's pixel to a specific
- Xcolor number (a reference to a color value through a "color register")
- Xor setting a text character to a specific font number (a reference
- Xto a font through a "font register"). This is diagrammed below.
- X
- X
- X Track 1 |Set Inst 2| Note | Note | Set Inst 1 | Note | Note | Note |...
- X | |
- X +-------------+ |
- X | +------------------------------------+
- X | | +--------------------------------------------------------+
- X | +-------->|"piano" ---------------> (internal piano data) |
- X +----------->|"guitar" ---------------> (internal guitar data) |
- X |"Spanish guitar" -------> (internal Spanish guitar data)|
- X +-------->|"bass drum" ------------> (internal bass drum data) |
- X | +--------------------------------------------------------+
- X |
- X +---------+
- X |
- X Track 2 |Set Inst 4| Note | Note | Note | Note | Note | Note | Note |...
- X
- X
- X
- XLocating instrument data by name. "INS1" chunks in a SMUS score name
- Xthe instruments to use for that score. The player program uses these
- Xnames to locate instrument data.
- X
- XTo locate instrument data, the player performs these steps:
- X
- XFor each instrument register, check for a suitable instrument with
- Xthe right name. "Suitable" means usable with an available output
- Xdevice and driver. {Use case independent name comparisons.}
- X
- X1. Initialize the instrument register to point to a built-in default
- X instrument. {Every player program must have default instruments.
- X Simple programs stop here. For fancier programs, the default
- X instruments are a backstop in case the search fails.}
- X
- X2. Check any instrument FORMs embedded in the FORM SMUS. (This
- X is an "instrument cache".)
- X
- X3. Else check the default instruments.
- X
- X4. Else search the local "instrument library". (The library might
- X simply be a disk directory.)
- X
- X5. If all else fails, display the desired instrument name and
- X ask the user to pick an available one.
- X
- XThis algorithm can be implemented to varying degrees of fanciness.
- XIt's ok to stop searching after step 1, 2, 3, or 4. If exact instrument
- Xname matches fail, it's ok to try approximate matches. E.g. search
- Xfor any kind of "guitar" if you can't find a "Spanish guitar". In
- Xany case, a player only has to search for instruments while loading
- Xa score.
- X
- XWhen the embedded instruments are suitable, they save the program
- Xfrom asking the user to insert the "right" disk in a drive and searching
- Xthat disk for the "right" instrument. But it's just a cache. In practice,
- Xwe rarely move scores between environments so the cache often works.
- XWhen the score is moved, embedded instruments must be discarded (a
- Xcache miss) and other instrument data used.
- X
- XBe careful to distinguish an instrument's name from its filenameQthe
- Xcontents name vs. container name. A musical instrument FORM should
- Xcontain a NAME chunk that says what instrument it really is. Its filename,
- Xon the other hand, is a handle used to locate the FORM. Filenames
- Xare affected by external factors like drives, directories, and filename
- Xcharacter and length limits. Instrument names are not.
- X
- XIssue: Consider instrument naming conventions for consistency. Consider
- Xa naming convention that aids approximate matches. E.g. we could accept
- X"guitar, bass1" if we didn't find "guitar, bass". Failing that, we
- Xcould accept "guitar" or any name starting with "guitar".
- X
- XSet instrument events. If the player implements the set-instrument
- Xscore event, each track can change instrument numbers while playing.
- XThat is, it can switch between the loaded instruments.
- X
- XInitial instrument settings. Each time a score is played, every tracks'
- Xrunning state information must be initialized. Specifically, each
- Xtrack's instrument number should be initialized to its track number.
- XTrack 1 to instrument 1, etc. It's as if each track began with a
- Xset-instrument event.
- X
- XIn this way, programs that don't implement the set-instrument event
- Xstill assign an instrument to each track. The INS1 chunks imply these
- Xinitial instrument settings.
- X
- XMIDI Instruments
- X
- XAs mentioned above, A SMUS score can also ask for MIDI instruments.
- XThis is done by putting the MIDI channel and preset numbers in an
- XINS1 chunk with the instrument name. Some programs will honor these
- Xrequests while others will just find instruments by name.
- X
- XMIDI Recorder and sequencer programs may simply transcribe the MIDI
- Xchannel and preset commands in a recording session. For this purpose,
- Xset-MIDI-channel and set-MIDI-preset events can be embedded in a SMUS
- Xscore's tracks. Most programs should ignore these events. An editor
- Xprogram that wants to exchange scores with such programs should recognize
- Xthese events. It should let the user change them to the more general
- Xset-instrument events.
- X
- X
- X
- X3. Standard Data and Property Chunks
- X
- XA FORM SMUS contains a required property "SHDR" followed by any number
- Xof parallel "track" data chunks "TRAK". Optional property chunks such
- Xas "NAME", copyright "(c) ", and instrument reference "INS1" may also
- Xappear. Any of the properties may be shared over a LIST of FORMs SMUS
- Xby putting them in a PROP SMUS. [See the IFF reference.]
- X
- XRequired Property SHDR
- X
- XThe required property "SHDR" holds an SScoreHeader as defined in these
- XC declarations and following documentation. An SHDR specifies global
- Xinformation for the score. It must appear before the TRAKs in a FORM
- XSMUS.
- X
- X#define ID_SMUS MakeID('S', 'M', 'U', 'S')
- X#define ID_SHDR MakeID('S', 'H', 'D', 'R')
- X
- Xtypedef struct {
- X UWORD tempo; /* tempo, 128ths quarter note/minute */
- X UBYTE volume; /* overall playback volume 0 through 127 */
- X UBYTE ctTrack; /* count of tracks in the score */
- X } SScoreHeader;
- X
- X[Implementation details. In the C struct definitions in this memo,
- Xfields are filed in the order shown. A UBYTE field is packed into
- Xan 8-bit byte. Programs should set all "pad" fields to 0. MakeID is
- Xa C macro defined in the main IFF document and in the source file
- XIFF.h.]
- X
- XThe field tempo gives the nominal tempo for all tracks in the score.
- XIt is expressed in 128ths of a quarter note per minute, i.e. 1 represents
- X1 quarter note per 128 minutes while 12800 represents 100 quarter
- Xnotes per minute. You may think of this as a fixed point fraction
- Xwith a 9-bit integer part and a 7-bit fractional part (to the right
- Xof the point). A course-tempoed program may simply shift tempo right
- Xby 7 bits to get a whole number of quarter notes per minute. The tempo
- Xfield can store tempi in the range 0 up to 512. The playback program
- Xmay adjust this tempo, perhaps under user control.
- X
- XActually, this global tempo could actually be just an initial tempo
- Xif there are any "set tempo" SEvents inside the score (see TRAK, below).
- XOr the global tempo could be scaled by "scale tempo" SEvents inside
- Xthe score. These are potential extensions that can safely be ignored
- Xby current programs. [See More SEvents To Be Defined, below.]
- X
- XThe field volume gives an overall nominal playback volume for all
- Xtracks in the score. The range of volume values 0 through 127 is like
- Xa MIDI key velocity value. The playback program may adjust this volume,
- Xperhaps under direction of a user "volume control".
- X
- XActually, this global volume level could be scaled by dynamic-mark
- XSEvents inside the score (see TRAK, below).
- X
- XThe field ctTrack holds the count of tracks, i.e. the number of TRAK
- Xchunks in the FORM SMUS (see below). This information helps the reader
- Xprepare for the following data.
- X
- XA playback program will typically load the score and call a driver
- Xroutine PlayScore(tracks, tempo, volume), supplying the tempo and
- Xvolume from the SHDR chunk.
- X
- XOptional Text Chunks NAME, (c), AUTH, ANNO
- X
- XSeveral text chunks may be included in a FORM SMUS to keep ancillary
- Xinformation.
- X
- XThe optional property "NAME" names the musical score, for instance
- X"Fugue in C".
- X
- XThe optional property "(c)J" holds a copyright notice for the score.
- XThe chunk ID "(c)J" serves the function of the copyright characters
- X")J". E.g. a "(c)J" chunk containing "1986 Electronic Arts" means
- X") 1986 Electronic Arts".
- X
- XThe optional property "AUTH" holds the name of the score's author.
- X
- XThe chunk types "NAME", "(c) ", and "AUTH" are property chunks. Putting
- Xmore than one NAME (or other) property in a FORM is redundant. Just
- Xthe last NAME counts. A property should be shorter than 256 characters.
- XProperties can appear in a PROP SMUS to share them over a LIST of
- XFORMs SMUS.
- X
- XThe optional data chunk "ANNO" holds any text annotations typed in
- Xby the author.
- X
- XAn ANNO chunk is not a property chunk, so you can put more than one
- Xin a FORM SMUS. You can make ANNO chunks any length up to 231 - 1
- Xcharacters, but 32767 is a practical limit. Since they're not properties,
- XANNO chunks don't belong in a PROP SMUS. That means they can't be
- Xshared over a LIST of FORMs SMUS.
- X
- XSyntactically, each of these chunks contains an array of 8-bit ASCII
- Xcharacters in the range R S (SP, hex 20) through R~S (tilde, hex 7F),
- Xjust like a standard "TEXT" chunk. [See "Strings, String Chunks, and
- XString Properties" in "EA IFF 85" Electronic Arts Interchange File
- XFormat.] The chunk's ckSize field holds the count of characters.
- X
- X#define ID_NAME MakeID('N', 'A', 'M', 'E')
- X/* NAME chunk contains a CHAR[], the musical score's name. */
- X
- X#define ID_Copyright MakeID('(', 'c', ')', ' ')
- X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
- X
- X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
- X/* AUTH chunk contains a CHAR[], the name of the score's author. */
- X
- X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
- X/* ANNO chunk contains a CHAR[], author's text annotations. */
- X
- XRemember to store a 0 pad byte after any odd-length chunk.
- X
- XOptional Property INS1
- X
- XThe "INS1" chunks in a FORM SMUS identify the instruments to use for
- Xthis score. A program can ignore INS1 chunks and stick with its built-in
- Xdefault instrument assignments. Or it can use them to locate instrument
- Xdata. [See "Instrument Registers" in section 2, above.]
- X
- X#define ID_INS1 MakeID('I', 'N', 'S', '1')
- X
- X/* Values for the RefInstrument field "type". */
- X#define INS1_Name 0 /* just use the name; ignore data1, data2 */
- X#define INS1_MIDI 1 /* <<data1, data2> = MIDI <<channel, preset> */
- X
- Xtypedef struct {
- X UBYTE register; /* set this instrument register number */
- X UBYTE type; /* instrument reference type */
- X UBYTE data1, data2; /* depends on the "type" field */
- X CHAR name[]; /* instrument name */
- X } RefInstrument;
- X
- XAn INS1 chunk names the instrument for instrument register number
- Xregister. The register field can range from 0 through 255. In practice,
- Xmost scores will need only a few instrument registers.
- X
- XThe name field gives a text name for the instrument. The string length
- Xcan be determined from the ckSize of the INS1 chunk. The string is
- Xsimply an array of 8-bit ASCII characters in the range R S (SP, hex
- X20) through R~S (tilde, hex 7F).
- X
- XBesides the instrument name, an INS1 chunk has two data numbers to
- Xhelp locate an instrument. The use of these data numbers is controlled
- Xby the type field. A value type = INS1_Name means just find an instrument
- Xby name. In this case, data1 and data2 should just be set to 0. A
- Xvalue type = INS1_MIDI means look for an instrument on MIDI channel
- X# data1, preset # data2. Programs and computers without MIDI outputs
- Xwill just ignore the MIDI data. They'll always look for the named
- Xinstrument. Other values of the type field are reserved for future
- Xstandardization.
- X
- XSee section 2, above, for the algorithm for locating instrument data
- Xby name.
- X
- XObsolete Property INST
- X
- XThe chunk type "INST" is obsolete in SMUS. It was revised to form
- Xthe "INS1" chunk.
- X
- XData Chunk TRAK
- X
- XThe main contents of a score is stored in one or more TRAK chunks
- Xrepresenting parallel "tracks". One TRAK chunk per track.
- X
- XThe contents of a TRAK chunk is an array of 16-bit "events" such as
- X"note", "rest", and "set instrument". Events are really commands to
- Xa simple scheduler, stored in time order. The tracks can be polyphonic,
- Xthat is, they can contain chorded "note" events.
- X
- XEach event is stored as an "SEvent" record. ("SEvent" means "simple
- Xmusical event".) Each SEvent has an 8-bit type field called an "sID"
- Xand 8 bits of type-dependent data. This is like a machine language
- Xinstruction with an 8-bit opcode and an 8-bit operand.
- X
- XThis format is extensible since new event types can be defined in
- Xthe future. The "note" and "rest" events are the only ones that every
- Xprogram must understand. We will carefully design any new event types
- Xso that programs can safely skip over unrecognized events in a score.
- X
- XCaution: SID codes must be allocated by a central clearinghouse to
- Xavoid conflicts.
- X
- XHere are the C type definitions for TRAK and SEvent and the currently
- Xdefined sID values. Afterward are details on each SEvent.
- X
- X#define ID_TRAK MakeID('T', 'R', 'A', 'K')
- X
- X/* TRAK chunk contains an SEvent[]. */
- X
- X/* SEvent: Simple musical event. */
- Xtypedef struct {
- X UBYTE sID; /* SEvent type code */
- X UBYTE data; /* sID-dependent data */
- X } SEvent;
- X
- X/* SEvent type codes "sID". */
- X#define SID_FirstNote 0
- X#define SID_LastNote 127 /* sIDs in the range SID_FirstNote through
- X * SID_LastNote (sign bit = 0) are notes. The
- X * sID is the MIDI tone number (pitch). */
- X#define SID_Rest 128 /* a rest (same data format as a note). */
- X
- X#define SID_Instrument 129 /* set instrument number for this
- Xtrack. */
- X#define SID_TimeSig 130 /* set time signature for this track. */
- X#define SID_KeySig 131 /* set key signature for this track. */
- X#define SID_Dynamic 132 /* set volume for this track. */
- X#define SID_MIDI_Chnl 133 /* set MIDI channel number (sequencers) */
- X#define SID_MIDI_Preset 134 /* set MIDI preset number (sequencers) */
- X
- X/* SID values 144 through 159: reserved for Instant Music SEvents. */
- X
- X/* Remaining sID values up through 254: reserved for future
- X * standardization. */
- X
- X#define SID_Mark 255 /* sID reserved for an end-mark in RAM. */
- X
- XNote and Rest SEvents
- X
- XThe note and rest SEvents SID_FirstNote through SID_Rest have the
- Xfollowing structure overlaid onto the SEvent structure:
- X
- Xtypedef struct {
- X UBYTE tone; /* MIDI tone number 0 to 127; 128 = rest */
- X unsigned chord :1, /* 1 = a chorded note */
- X tieOut :1, /* 1 = tied to the next note or chord */
- X nTuplet :2, /* 0 = none, 1 = triplet, 2 = quintuplet,
- X * 3 = septuplet */
- X dot :1, /* dotted note; multiply duration by 3/2 */
- X division :3; /* basic note duration is 2-division: 0 = whole
- X * note, 1 = half note, 2 = quarter note, I
- X * 7 = 128th note */
- X } SNote;
- X
- X[Implementation details. Unsigned ":n" fields are packed into n bits
- Xin the order shown, most significant bit to least significant bit.
- XAn SNote fits into 16 bits like any other SEvent. Warning: Some compilers
- Xdon't implement bit-packed fields properly. E.g. Lattice 68000 C pads
- Xa group of bit fields out to a LONG, which would make SNote take 5-bytes!
- XIn that situation, use the bit-field constants defined below.]
- X
- XThe SNote structure describes one "note" or "rest" in a track. The
- Xfield SNote.tone, which is overlaid with the SEvent.sID field, indicates
- Xthe MIDI tone number (pitch) in the range 0 through 127. A value of
- X128 indicates a rest.
- X
- XThe fields nTuplet, dot, and division together give the duration of
- Xthe note or rest. The division gives the basic duration: whole note,
- Xhalf note, etc. The dot indicates if the note or rest is dotted. A
- Xdotted note is 3/2 as long as an undotted note. The value nTuplet
- X(0 through 3) tells if this note or rest is part of an N-tuplet of
- Xorder 1 (normal), 3, 5, or 7; an N-tuplet of order (2J*JnTupletJ+J1).
- XA triplet note is 2/3 as long as a normal note, while a quintuplet
- Xis 4/5 as long and a septuplet is 6/7 as long.
- X
- XPutting these three fields together, the duration of the note or rest
- Xis 2-division * {1, 3/2} * {1, 2/3, 4/5, 6/7}
- X
- XThese three fields are contiguous so you can easily convert to your
- Xlocal duration encoding by using the combined 6 bits as an index into
- Xa mapping table.
- X
- XThe field chord indicates if the note is chorded with the following
- Xnote (which is supposed to have the same duration). A group of notes
- Xmay be chorded together by setting the chord bit of all but the last
- Xone. (In the terminology of SSSP and GSCR, setting the chord bit to
- X1 makes the "entry delay" 0.) A monophonic-track player can simply
- Xignore any SNote event whose chord bit is set, either by discarding
- Xit when reading the track or by skipping it when playing the track.
- X
- XPrograms that create polyphonic tracks are expected to store the most
- Ximportant note of each chord last, which is the note with the 0 chord
- Xbit. This way, monophonic programs will play the most important note
- Xof the chord. The most important note might be the chord's root note
- Xor its melody note.
- X
- XIf the field tieOut is set, the note is tied to the following note
- Xin the track if the following note has the same pitch. A group of
- Xtied notes is played as a single note whose duration is the sum of
- Xthe component durations. Actually, the tie mechanism ties a group
- Xof one or more chorded notes to another group of one or more chorded
- Xnotes. Every note in a tied chord should have its tieOut bit set.
- X
- XOf course, the chord and tieOut fields don't apply to SID_Rest SEvents.
- X
- XPrograms should be robust enough to ignore an unresolved tie, i.e.
- Xa note whose tieOut bit is set but isn't followed by a note of the
- Xsame pitch. If that's true, monophonic-track programs can simply ignore
- Xchorded notes even in the presense of ties. That is, tied chords pose
- Xno extra problems.
- X
- XThe following diagram shows some combinations of notes and chords
- Xtied to notes and chords. The text below the staff has a column for
- Xeach SNote SEvent to show the pitch, chord bit, and tieOut bit.
- X
- X
- X
- X (figure)
- X
- X
- X
- X
- XIf you read the above track into a monophonic-track program, it'll
- Xstrip out the chorded notes and ignore unresolved ties. You'll end
- Xup with:
- X
- X
- X
- X (figure)
- X
- X
- X
- X
- XA rest event (sID = SID_Rest) has the same SEvent.data field as a
- Xnote. It tells the duration of the rest. The chord and tieOut fields
- Xof rest events are ignored.
- X
- XWithin a TRAK chunk, note and rest events appear in time order.
- X
- XInstead of the bit-packed structure SNote, it might be easier to assemble
- Xdata values by or-ing constants and to disassemble them by masking
- Xand shifting. In that case, use the following definitions.
- X
- X#define noteChord (1<<<<7) /* note is chorded to next note */
- X
- X#define noteTieOut (1<<<<6) /* tied to next note/chord */
- X
- X#define noteNShift 4 /* shift count for nTuplet field */
- X#define noteN3 (1<<<<noteNShift) /* note is a triplet */
- X#define noteN5 (2<<<<noteNShift) /* note is a quintuplet */
- X#define noteN7 (3<<<<noteNShift) /* note is a septuplet */
- X#define noteNMask noteN7 /* bit mask for the nTuplet field */
- X
- X#define noteDot (1<<<<3) /* note is dotted */
- X
- X#define noteD1 0 /* whole note division */
- X#define noteD2 1 /* half note division */
- X#define noteD4 2 /* quarter note division */
- X#define noteD8 3 /* eighth note division */
- X#define noteD16 4 /* sixteenth note division */
- X#define noteD32 5 /* thirty-secondth note division */
- X#define noteD64 6 /* sixty-fourth note division */
- X#define noteD128 7 /* 1/128 note division */
- X#define noteDMask noteD128 /* bit mask for the division field */
- X
- X#define noteDurMask 0x3F /* mask for combined duration fields */
- X
- XNote: The remaining SEvent types are optional. A writer program doesn't
- Xhave to generate them. A reader program can safely ignore them.
- X
- XSet Instrument SEvent
- X
- XOne of the running state variables of every track is an instrument
- Xnumber. An instrument number is the array index of an "instrument
- Xregister", which in turn points to an instrument. (See "Instrument
- XRegisters", in section 2.) This is like a color number in a bitmap;
- Xa reference to a color through a "color register".
- X
- XThe initial setting for each track's instrument number is the track
- Xnumber. Track 1 is set to instrument 1, etc. Each time the score is
- Xplayed, every track's instrument number should be reset to the track
- Xnumber.
- X
- XThe SEvent SID_Instrument changes the instrument number for a track,
- Xthat is, which instrument plays the following notes. Its SEvent.data
- Xfield is an instrument register number in the range 0 through 255.
- XIf a program doesn't implement the SID_Instrument event, each track
- Xis fixed to one instrument.
- X
- XSet Time Signature SEvent
- X
- XThe SEvent SID_TimeSig sets the time signature for the track. A "time
- Xsignature" SEvent has the following structure overlaid on the SEvent
- Xstructure:
- X
- Xtypedef struct {
- X UBYTE type; /* = SID_TimeSig */
- X unsigned timeNSig :5, /* time sig. "numerator" is timeNSig + 1 */
- X timeDSig :3; /* time sig. "denominator" is 2timeDSig:
- X * 0 = whole note, 1 = half note, 2 = quarter
- X * note, I 7 = 128th note */
- X } STimeSig;
- X
- X[Implementation details. Unsigned ":n" fields are packed into n bits
- Xin the order shown, most significant bit to least significant bit.
- XAn STimeSig fits into 16 bits like any other SEvent. Warning: Some
- Xcompilers don't implement bit-packed fields properly. E.g. Lattice
- XC pads a group of bit fields out to a LONG, which would make an STimeSig
- Xtake 5-bytes! In that situation, use the bit-field constants defined
- Xbelow.]
- X
- XThe field type contains the value SID_TimeSig, indicating that this
- XSEvent is a "time signature" event. The field timeNSig indicates the
- Xtime signature "numerator" is timeNSig + 1, that is, 1 through 32
- Xbeats per measure. The field timeDSig indicates the time signature
- X"denominator" is 2timeDSig, that is each "beat" is a 2-timeDSig note
- X(see SNote division, above). So 4/4 time is expressed as timeNSig
- X= 3, timeDSig = 2.
- X
- XThe default time signature is 4/4 time.
- X
- XBeware that the time signature has no effect on the score's playback.
- XTempo is uniformly expressed in quarter notes per minute, independent
- Xof time signature. (Quarter notes per minute equals beats per minute
- Xonly if timeDSig = 2, n/4 time). Nonetheless, any program that has
- Xtime signatures should put them at the beginning of each TRAK when
- Xcreating a FORM SMUS because music editors need them.
- X
- XInstead of the bit-packed structure STimeSig, it might be easier to
- Xassemble data values by or-ing constants and to disassemble them by
- Xmasking and shifting. In that case, use the following definitions.
- X
- X#define timeNMask 0xF8 /* bit mask for the timeNSig field */
- X#define timeNShift 3 /* shift count for timeNSig field */
- X
- X#define timeDMask 0x07 /* bit mask for the timeDSig field */
- X
- XKey Signature SEvent
- X
- XAn SEvent SID_KeySig sets the key signature for the track. Its data
- Xfield is a UBYTE number encoding a major key:
- X
- Xdata key music notation data key music notation
- XJ0 C maj
- XJ1 G # J8 F b
- XJ2 D ## J9 Bb bb
- XJ3 A ### 10 Eb bbb
- XJ4 E #### 11 Ab bbbb
- XJ5 B ##### 12 Db bbbbb
- XJ6 F# ###### 13 Gb bbbbbb
- XJ7 C# ####### 14 Cb bbbbbbb
- X
- XA SID_KeySig SEvent changes the key for the following notes in that
- Xtrack. C major is the default key in every track before the first
- XSID_KeySig SEvent.
- X
- XDynamic Mark SEvent
- X
- XAn SEvent SID_Dynamic represents a dynamic mark like ppp and fff in
- XCommon Music Notation. Its data field is a MIDI key velocity number
- X0 through 127. This sets a "volume control" for following notes in
- Xthe track. This "track volume control" is scaled by the overall score
- Xvolume in the SHDR chunk.
- X
- XThe default dynamic level is 127 (full volume).
- X
- XSet MIDI Channel SEvent
- X
- XThe SEvent SID_MIDI_Chnl is for recorder programs to record the set-MIDI-channe
- Xl low level event. The data byte contains a MIDI channel number. Other
- Xprograms should use instrument registers instead.
- X
- XSet MIDI Preset SEvent
- X
- XThe SEvent SID_MIDI_Preset is for recorder programs to record the
- Xset-MIDI-preset low level event. The data byte contains a MIDI preset
- Xnumber. Other programs should use instrument registers instead.
- X
- XInstant Music Private SEvents
- X
- XSixteen SEvents are used for private data for the Instant Music program.
- XSID values 144 through 159 are reserved for this purpose. Other programs
- Xshould skip over these SEvents.
- X
- XEnd-Mark SEvent
- X
- XThe SEvent type SID_Mark is reserved for an end marker in working
- Xmemory. This event is never stored in a file. It may be useful if
- Xyou decide to use the filed TRAK format intact in working memory.
- X
- XMore SEvents To Be Defined
- X
- XMore SEvents can be defined in the future. The sID codes 133 through
- X143 and 160 through 254 are reserved for future needs. Caution: sID
- Xcodes must be allocated by a central "clearinghouse" to avoid conflicts.
- XWhen this SMUS standard passes the "draft" state, Commodore-Amiga
- Xwill be in charge of this activity.
- X
- XThe following SEvent types are under consideration and should not
- Xyet be used.
- X
- XIssue: A "change tempo" SEvent changes tempo during a score. Changing
- Xthe tempo affects all tracks, not just the track containing the change
- Xtempo event.
- X
- XOne possibility is a "scale tempo" SEvent SID_ScaleTempo that rescales
- Xthe global tempo:
- XcurrentTempo := globalTempo * (data + 1) / 128
- X
- XThis can scale the global tempo (in the SHDR) anywhere from x1/128
- Xto x2 in roughly 1% increments.
- X
- XAn alternative is two events SID_SetHTempo and SID_SetLTempo. SID_SetHTempo
- Xgives the high byte and SID_SetLTempo gives the low byte of a new
- Xtempo setting, in 128ths quarter note/minute. SetHTempo automatically
- Xsets the low byte to 0, so the SetLTempo event isn't needed for course
- Xsettings. In this scheme, the SHDR's tempo is simply a starting tempo.
- X
- XAn advantage of SID_ScaleTempo is that the playback program can just
- Xalter the global tempo to adjust the overall performance time and
- Xstill easily implement tempo variations during the score. But the
- X"set tempo" SEvent may be simpler to generate.
- X
- XIssue: The events SID_BeginRepeat and SID_EndRepeat define a repeat
- Xspan for one track. The span of events between a BeginRepeat and an
- XEndRepeat is played twice. The SEvent.data field in the BeginRepeat
- Xevent could give an iteration count,1 through 255 times or 0 for "repeat
- Xforever".
- X
- XRepeat spans can be nested. All repeat spans automatically end at
- Xthe end of the track.
- X
- XAn event SID_Ending begins a section like "first ending" or "second
- Xending". The SEvent.data field gives the ending number. This SID_Ending
- Xevent only applies to the innermost repeat group. (Consider generalizing
- Xit.)
- X
- XA more general alternative is a "subtrack" or "subscore" event. A
- X"subtrack" event is essentially a "subroutine call" to another series
- Xof SEvents. This is a nice way to encode all the possible variations
- Xof repeats, first endings, codas, and such.
- X
- XTo define a subtrack, we must demark its start and end. One possibility
- Xis to define a relative brach-to-subtrack event SID_BSR and a return-from-subtr
- Xack event SID_RTS. The 8-bit data field in the SID_BSR event can reach
- Xas far as 512 SEvents. A second possibility is to call a subtrack
- Xby index number, with an IFF chunk outside the TRAK defining the start
- Xand end of all subtracks. This is very general since a portion of
- Xone subtrack can be used as another subtrack. It also models the tape
- Xrecording practice of first "laying down a track" and then selecting
- Xportions of it to play and repeat. To embody the music theory idea
- Xof playing a sequence like "ABBA", just compose the "main" track entirely
- Xof subtrack events. A third possibility is to use a numbered subtrack
- Xchunk "STRK" for each subroutine.
- X
- X
- X
- X
- X4. Private Chunks
- X
- XAs in any IFF FORM, there can be private chunks in a FORM SMUS that
- Xare designed for one particular program to store its private information.
- XAll IFF reader programs skip over unrecognized chunks, so the presense
- Xof private chunks can't hurt.
- X
- XInstant Music stores some global score information in a chunk of ID
- X"IRev".
- X
- X
- X
- XAppendix A. Quick Reference
- X
- XType Definitions
- X
- XHere's a collection of the C type definitions in this memo. In the
- X"struct" type definitions, fields are filed in the order shown. A
- XUBYTE field is packed into an 8-bit byte. Programs should set all
- X"pad" fields to 0.
- X
- X#define ID_SMUS MakeID('S', 'M', 'U', 'S')
- X#define ID_SHDR MakeID('S', 'H', 'D', 'R')
- X
- Xtypedef struct {
- X UWORD tempo; /* tempo, 128ths quarter note/minute */
- X UBYTE volume; /* overall playback volume 0 through 127 */
- X UBYTE ctTrack; /* count of tracks in the score */
- X } SScoreHeader;
- X
- X#define ID_NAME MakeID('N', 'A', 'M', 'E')
- X/* NAME chunk contains a CHAR[], the musical score's name. */
- X
- X#define ID_Copyright MakeID('(', 'c', ')', ' ')
- X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
- X
- X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
- X/* AUTH chunk contains a CHAR[], the name of the score's author. */
- X
- X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
- X/* ANNO chunk contains a CHAR[], author's text annotations. */
- X
- X#define ID_INS1 MakeID('I', 'N', 'S', '1')
- X
- X/* Values for the RefInstrument field "type". */
- X#define INS1_Name 0 /* just use the name; ignore data1, data2 */
- X#define INS1_MIDI 1 /* <<data1, data2> = MIDI <<channel, preset> */
- X
- Xtypedef struct {
- X UBYTE register; /* set this instrument register number */
- X UBYTE type; /* instrument reference type */
- X UBYTE data1, data2; /* depends on the "type" field */
- X CHAR name[]; /* instrument name */
- X } RefInstrument;
- X
- X#define ID_TRAK MakeID('T', 'R', 'A', 'K')
- X/* TRAK chunk contains an SEvent[]. */
- X
- X/* SEvent: Simple musical event. */
- Xtypedef struct {
- X UBYTE sID; /* SEvent type code */
- X UBYTE data; /* sID-dependent data */
- X } SEvent;
- X
- X/* SEvent type codes "sID". */
- X#define SID_FirstNote 0
- X#define SID_LastNote 127 /* sIDs in the range SID_FirstNote through
- X * SID_LastNote (sign bit = 0) are notes. The
- X * sID is the MIDI tone number (pitch). */
- X#define SID_Rest 128 /* a rest (same data format as a note). */
- X
- X#define SID_Instrument 129 /* set instrument number for this
- Xtrack. */
- X#define SID_TimeSig 130 /* set time signature for this track. */
- X#define SID_KeySig 131 /* set key signature for this track. */
- X#define SID_Dynamic 132 /* set volume for this track. */
- X#define SID_MIDI_Chnl 133 /* set MIDI channel number (sequencers) */
- X#define SID_MIDI_Preset 134 /* set MIDI preset number (sequencers) */
- X
- X/* SID values 144 through 159: reserved for Instant Music SEvents. */
- X
- X/* Remaining sID values up through 254: reserved for future
- X * standardization. */
- X
- X#define SID_Mark 255 /* sID reserved for an end-mark in RAM. */
- X
- X/* SID_FirstNote..SID_LastNote, SID_Rest SEvents */
- Xtypedef struct {
- X UBYTE tone; /* MIDI tone number 0 to 127; 128 = rest */
- X unsigned chord :1, /* 1 = a chorded note */
- X tieOut :1, /* 1 = tied to the next note or chord */
- X nTuplet :2, /* 0 = none, 1 = triplet, 2 = quintuplet,
- X * 3 = septuplet */
- X dot :1, /* dotted note; multiply duration by 3/2 */
- X division :3; /* basic note duration is 2-division: 0 = whole
- X * note, 1 = half note, 2 = quarter note, I
- X * 7 = 128th note */
- X } SNote;
- X
- X#define noteChord (1<<<<7) /* note is chorded to next note */
- X
- X#define noteTieOut (1<<<<6) /* tied to next note/chord */
- X
- X#define noteNShift 4 /* shift count for nTuplet field */
- X#define noteN3 (1<<<<noteNShift) /* note is a triplet */
- X#define noteN5 (2<<<<noteNShift) /* note is a quintuplet */
- X#define noteN7 (3<<<<noteNShift) /* note is a septuplet */
- X#define noteNMask noteN7 /* bit mask for the nTuplet field */
- X
- X#define noteDot (1<<<<3) /* note is dotted */
- X
- X#define noteD1 0 /* whole note division */
- X#define noteD2 1 /* half note division */
- X#define noteD4 2 /* quarter note division */
- X#define noteD8 3 /* eighth note division */
- X#define noteD16 4 /* sixteenth note division */
- X#define noteD32 5 /* thirty-secondth note division */
- X#define noteD64 6 /* sixty-fourth note division */
- X#define noteD128 7 /* 1/128 note division */
- X#define noteDMask noteD128 /* bit mask for the division field */
- X
- X#define noteDurMask 0x3F /* mask for combined duration fields */
- X
- X/* SID_Instrument SEvent */
- X/* "data" value is an instrument register number 0 through 255. */
- X
- X/* SID_TimeSig SEvent */
- Xtypedef struct {
- X UBYTE type; /* = SID_TimeSig */
- X unsigned timeNSig :5, /* time sig. "numerator" is timeNSig + 1 */
- X timeDSig :3; /* time sig. "denominator" is 2timeDSig:
- X * 0 = whole note, 1 = half note, 2 = quarter
- X * note, I 7 = 128th note */
- X } STimeSig;
- X
- X#define timeNMask 0xF8 /* bit mask for the timeNSig field */
- X#define timeNShift 3 /* shift count for timeNSig field */
- X
- X#define timeDMask 0x07 /* bit mask for the timeDSig field */
- X
- X/* SID_KeySig SEvent */
- X/* "data" value 0 = Cmaj; 1 through 7 = G,D,A,E,B,F#,C#;
- X * 8 through 14 = F,Bb,Eb,Ab,Db,Gb,Cb. */
- X
- X/* SID_Dynamic SEvent */
- X/* "data" value is a MIDI key velocity 0..127. */
- X
- XSMUS Regular Expression
- X
- XHere's a regular expression summary of the FORM SMUS syntax. This
- Xcould be an IFF file or part of one.
- X
- XSMUS ::= "FORM" #{ "SMUS" SHDR [NAME] [Copyright] [AUTH] [IRev]
- X ANNO* INS1* TRAK* InstrForm* }
- X
- XSHDR ::= "SHDR" #{ SScoreHeader }
- XNAME ::= "NAME" #{ CHAR* } [0]
- XCopyright ::= "(c) " #{ CHAR* } [0]
- XAUTH ::= "AUTH" #{ CHAR* } [0]
- XIRev ::= "IRev" #{ ... }
- X
- XANNO ::= "ANNO" #{ CHAR* } [0]
- XINS1 ::= "INS1" #{ RefInstrument } [0]
- X
- XTRAK ::= "TRAK" #{ SEvent* }
- X
- XInstrForm ::= "FORM" #{ ... }
- X
- XThe token "#" represents a ckSize LONG count of the following {braced}
- Xdata bytes. Literal items are shown in "quotes", [square bracket items]
- Xare optional, and "*" means 0 or more replications. A sometimes-needed
- Xpad byte is shown as "[0]".
- X
- XActually, the order of chunks in a FORM SMUS is not as strict as this
- Xregular expression indicates. The SHDR, NAME, Copyright, AUTH, IRev,
- XANNO, and INS1 chunks may appear in any order, as long as they precede
- Xthe TRAK chunks.
- X
- XThe chunk RInstrFormS represents any kind of instrument data FORM
- Xembedded in the FORM SMUS. For example, see the document "8SVX" IFF
- X8-Bit Sampled Voice. Of course, a recipient program will ignore an
- Xinstrument FORM if it doesn't recognize that FORM type.
- X
- X
- X
- XAppendix B. SMUS Example
- X
- XHere's a box diagram for a simple example, a SMUS with two instruments
- Xand two tracks. Each track contains 1 note event and 1 rest event.
- X
- X
- X
- X +-----------------------------------------+ ------
- X |'FORM' 94 | ^
- X | +-----------------------------------+ | |
- X | |'SMUS' | | |
- X | +-----------------------------------+ | |
- X | | +-------------------------------+ | | |
- X | | | 'SHDR' 4 | | | |
- X | | | 12800, 127, 2 | | | |
- X | | +-------------------------------+ | | |
- X | | +-------------------------------+ | | |
- X | | | 'NAME' 10 | | | |
- X | | | 'Fugue in C' | | | |
- X | | +-------------------------------+ | | |
- X | | +-------------------------------+ | |
- X | | | 'INS1' 9 | | | (94 bytes)
- X | | | 1,0,0,0,'piano' | | |
- X | | +-------------------------------+ | | |
- X | | 0 | | |
- X | | +-------------------------------+ | | |
- X | | | 'INS1' 10 | | | |
- X | | | 2,0,0,0,'guitar' | | | |
- X | | +-------------------------------+ | | |
- X | | +-------------------------------+ | | |
- X | | | 'TRAK' 4 | | | |
- X | | | 60, 16, 128, 16 | | | |
- X | | +-------------------------------+ | | |
- X | | +-------------------------------+ | | |
- X | | | 'TRAK' 4 | | | |
- X | | | 128, 16, 60, 16 | | | |
- X | | +-------------------------------+ | | |
- X | +-----------------------------------+ | V
- X +-----------------------------------------+ -----
- X
- X
- X
- XAppendix B. Standards Committee
- X
- XThe following people contributed to the design of this IFF standard:
- X
- XBob "Kodiak" Burns, Commodore-Amiga
- XR. J. Mical, Commodore-Amiga
- XJerry Morrison, Electronic Arts
- XGreg Riker, Electronic Arts
- XSteve Shaw, Electronic Arts
- XBarry Walsh, Commodore-Amiga
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- XThe "0" after the first INS1 chunk is a pad byte.
- X
- X
- X
- XAppendix C. Standards Committee
- X
- XThe following people contributed to the design of this SMUS standard:
- X
- XRalph Bellafatto, Cherry Lane Technologies
- XGeoff Brown, Uhuru Sound Software
- XSteve Hayes, Electronic Arts
- XJerry Morrison, Electronic Arts
- //END
- : end of archive.
- exit 0
- --
- Peter da Silva. `-_-'
- <peter@sugar.hackercorp.com>.
-
-